Может ли директива angular передавать аргументы в функции в выражениях, указанных в атрибутах директивы?
У меня есть директива формы, которая использует указанный атрибут callback
с областью выделения:
scope: { callback: '&' }
Он находится внутри ng-repeat
, поэтому выражение, которое я передаю, включает в себя id
объекта в качестве аргумента функции обратного вызова:
<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>
Когда я закончил с директивой, он вызывает $scope.callback()
из своей функции контроллера. В большинстве случаев это нормально, и все, что я хочу сделать, но иногда я хотел бы добавить еще один аргумент из самого directive
.
Есть ли выражение angular, которое позволит это: $scope.callback(arg2)
, в результате чего callback
вызывается с помощью arguments = [item.id, arg2]
?
Если нет, то какой самый простой способ сделать это?
Я обнаружил, что это работает:
<directive
ng-repeat = "item in stuff"
callback = "callback"
callback-arg="item.id"/>
С
scope { callback: '=', callbackArg: '=' }
и директивный вызов
$scope.callback.apply(null, [$scope.callbackArg].concat([arg2, arg3]) );
Но я не думаю, что это особенно опрятно, и это включает в себя добавление лишних вещей в область выделения.
Есть ли лучший способ?
Плункерная площадка здесь (консоль открыта).
Ответы
Ответ 1
Если вы заявляете свой обратный вызов, как упоминалось в @lex82, например
callback = "callback(item.id, arg2)"
Вы можете вызвать метод обратного вызова в области директивы с помощью карты объектов, и он будет правильно связывать. Как
scope.callback({arg2:"some value"});
не требуя для $parse. Смотрите мою скрипку (консольный журнал) http://jsfiddle.net/k7czc/2/
Обновить. Это небольшой пример этого в документации :
& или & attr - обеспечивает способ выполнения выражения в контексте родительский охват. Если имя attr не указано, имя атрибута предполагается, что оно совпадает с локальным именем. Определенное и видимое определение области: { localFn: '& myAttr'}, затем изолировать свойство scope localFn будет указывать на обертка функций для выражения count = count + value. Часто желательно передавать данные из изолированного объема посредством выражения и в родительскую область, это можно сделать, передав карту локальных имена переменных и значения в оболочку выражения fn. Например, если выражение является приращением (суммой), то мы можем указать сумму значение, вызывая localFn как localFn ({amount: 22}).
Ответ 2
Ничего плохого в других ответах, но я использую следующий метод при передаче функций в атрибуте директивы.
Оставьте круглую скобку, включив директиву в свой html:
<my-directive callback="someFunction" />
Затем "разворачивать" функцию в вашей директивной ссылке или контроллере. вот пример:
app.directive("myDirective", function() {
return {
restrict: "E",
scope: {
callback: "&"
},
template: "<div ng-click='callback(data)'></div>", // call function this way...
link: function(scope, element, attrs) {
// unwrap the function
scope.callback = scope.callback();
scope.data = "data from somewhere";
element.bind("click",function() {
scope.$apply(function() {
callback(data); // ...or this way
});
});
}
}
}]);
Шаг "разворачивания" позволяет вызывать функцию с использованием более естественного синтаксиса. Это также гарантирует правильность работы директивы, даже если она вложена в другие директивы, которые могут передавать функцию. Если вы не сделали разворачивание, тогда, если у вас есть такой сценарий:
<outer-directive callback="someFunction" >
<middle-directive callback="callback" >
<inner-directive callback="callback" />
</middle-directive>
</outer-directive>
Тогда в вашей внутренней директиве вы получите что-то подобное:
callback()()()(data);
Что произойдет в других сценариях вложенности.
Я адаптировал этот метод из превосходной статьи Дэна Вахлина в http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters
Я добавил шаг развертывания, чтобы сделать вызов функции более естественным и решить проблему размещения, с которой я столкнулся в проекте.
Ответ 3
В директиве (myDirective
):
...
directive.scope = {
boundFunction: '&',
model: '=',
};
...
return directive;
В шаблоне директивы:
<div
data-ng-repeat="item in model"
data-ng-click='boundFunction({param: item})'>
{{item.myValue}}
</div>
В источнике:
<my-directive
model='myData'
bound-function='myFunction(param)'>
</my-directive>
... где myFunction
определяется в контроллере.
Обратите внимание, что param
в шаблоне директивы аккуратно привязывается к param
в источнике и устанавливается на item
.
Чтобы вызвать из свойства link
директивы ( "внутри" ), используйте очень похожий подход:
...
directive.link = function(isolatedScope) {
isolatedScope.boundFunction({param: "foo"});
};
...
return directive;
Ответ 4
Да, есть лучший способ: вы можете использовать $parse service в своей директиве для оценки выражения в контексте родительского scope при привязке определенных идентификаторов в выражении к значениям, видимым только внутри вашей директивы:
$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });
Добавьте эту строку в функцию ссылки директивы, где вы можете получить доступ к атрибутам директивы.
Атрибут обратного вызова может быть установлен как callback = "callback(item.id, arg2)"
, потому что arg2 привязан к вашемуSecondArgument службой $parse внутри директивы. Директивы типа ng-click
позволяют вам получить доступ к событию клика с помощью идентификатора $event
внутри выражения, переданного в директиву, используя именно этот механизм.
Обратите внимание, что вам не нужно делать callback
членом вашей изолированной области с помощью этого решения.
Ответ 5
У меня работает следующее:
в директиве объявить это так:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
scope: {
myFunction: '=',
},
templateUrl: 'myDirective.html'
};
})
В шаблоне директивы используйте его следующим образом:
<select ng-change="myFunction(selectedAmount)">
И затем, когда вы используете директиву, передайте функцию следующим образом:
<data-my-directive
data-my-function="setSelectedAmount">
</data-my-directive>
Вы передаете функцию по ее объявлению, и она вызывается из директивы, а параметры заполняются.