我有一个表单指令,它使用带有隔离范围的指定callback
属性:
scope: { callback: '&' }
它位于ng-repeat
内,因此我传入的表达式包含对象的id
作为回调函数的参数:
<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>
当我完成指令时,它从其控制器函数调用$scope.callback()
。对于大多数情况来说这很好,这就是我想要做的,但有时我想在directive
内部添加另一个参数。
是否有一个允许这样的角度表达式:$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]) );
但我不认为它特别整洁,它涉及在隔离范围内增加额外的东西。
有更好的方法吗?
Plunker playground here(打开控制台)。
答案 0 :(得分:211)
如果你像@ lex82中提到的那样声明你的回调
callback = "callback(item.id, arg2)"
您可以使用对象映射在指令范围内调用回调方法,它可以正确地进行绑定。像
scope.callback({arg2:"some value"});
不需要$ parse。看我的小提琴(控制台日志)http://jsfiddle.net/k7czc/2/
更新:documentation中有一个小例子:
&安培;或&amp; attr - 提供在上下文中执行表达式的方法 父范围。如果未指定attr名称,则为属性名称 假定与本地名称相同。给定范围的小部件定义:{ localFn:'&amp; myAttr'},然后隔离范围属性localFn将指向 count = count + value表达式的函数包装器。经常 希望通过表达式从隔离范围传递数据 对于父作用域,可以通过传递本地地图来完成 变量名和值到表达式包装器fn中。 例如, 如果表达式是增量(金额),那么我们可以指定金额 将localFn称为localFn({amount:22})。
答案 1 :(得分:57)
其他答案没有错,但在指令属性中传递函数时使用以下技术。
在html中包含指令时不要使用括号:
<my-directive callback="someFunction" />
然后&#34;打开&#34;指令的链接或控制器中的功能。这是一个例子:
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
});
});
}
}
}]);
&#34;展开&#34; step允许使用更自然的语法调用函数。它还确保指令即使嵌套在可能传递函数的其他指令中也能正常工作。如果您没有进行展开,那么如果你有这样的场景:
<outer-directive callback="someFunction" >
<middle-directive callback="callback" >
<inner-directive callback="callback" />
</middle-directive>
</outer-directive>
然后你会在你的内部指令中得到类似的东西:
callback()()()(data);
在其他嵌套方案中会失败。
我从Dan Wahlin在http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters
的一篇优秀文章中采用了这种技巧我添加了展开步骤,使调用函数更自然,并解决了我在项目中遇到的嵌套问题。
答案 2 :(得分:39)
在指令(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
属性内调用(&#34;内部&#34;),请使用非常类似的方法:
...
directive.link = function(isolatedScope) {
isolatedScope.boundFunction({param: "foo"});
};
...
return directive;
答案 3 :(得分:15)
是的,有一种更好的方法:您可以使用指令中的$parse service来评估父作用域上下文中的表达式,同时将表达式中的某些标识符绑定到仅在指令内可见的值: / p>
$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });
将此行添加到指令的link函数中,您可以在其中访问指令的属性。
您的回调属性可能会设置为callback = "callback(item.id, arg2)"
,因为arg2由指令内的$ parse服务绑定到yourSecondArgument。像ng-click
这样的指令允许您通过使用这个机制传递给指令的表达式中的$event
标识符来访问click事件。
请注意,您不必使用此解决方案使callback
成为隔离范围的成员。
答案 4 :(得分:0)
对我来说,以下工作有效:
在指令中这样声明:
.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>
您通过函数的声明传递该函数,并从指令中调用该函数,并填充参数。