163

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 游乐场在这里(打开控制台)。

4

5 回答 5

220

如果您声明@lex82 提到的回调,例如

callback = "callback(item.id, arg2)"

您可以使用对象映射在指令范围内调用回调方法,它会正确地进行绑定。像

scope.callback({arg2:"some value"});

无需 $parse。请参阅我的小提琴(控制台日志)http://jsfiddle.net/k7czc/2/

更新:文档中有一个小例子:

& 或 &attr - 提供一种在父作用域的上下文中执行表达式的方法。如果未指定 attr 名称,则假定属性名称与本地名称相同。给定范围的小部件定义:{ localFn:'&myAttr' },然后隔离范围属性 localFn 将指向 count = count + value 表达式的函数包装器。通常希望通过表达式将数据从隔离范围传递到父范围,这可以通过将局部变量名称和值的映射传递到表达式包装器 fn 来完成。例如,如果表达式是 increment(amount),那么我们可以通过将 localFn 调用为 localFn({amount: 22}) 来指定数量值。

于 2013-11-10T13:58:18.940 回答
59

其他答案没有错,但是在指令属性中传递函数时,我使用了以下技术。

在你的 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); 

在其他嵌套场景中会失败。

我从 Dan Wahlin 在http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters的一篇优秀文章中改编了这项技术

我添加了展开步骤,以使调用函数更自然,并解决我在项目中遇到的嵌套问题。

于 2014-12-04T17:42:23.963 回答
47

在指令 ( 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;
于 2015-05-30T06:09:16.403 回答
16

是的,有一个更好的方法:您可以在指令中使用$parse 服务来评估父范围上下文中的表达式,同时将表达式中的某些标识符绑定到仅在指令内可见的值:

$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });

将此行添加到指令的链接函数中,您可以在其中访问指令的属性。

然后您的回调属性可能会设置为callback = "callback(item.id, arg2)"因为 arg2 被指令内的 $parse 服务绑定到 yourSecondArgument 。像这样的指令ng-click允许您$event通过使用这种机制传递给指令的表达式中的标识符来访问点击事件。

请注意,您不必callback使用此解决方案创建隔离范围的成员。

于 2013-11-10T13:38:08.200 回答
1

对我来说,以下工作:

在指令中声明它是这样的:

.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>

您通过其声明传递函数,并从指令调用它并填充参数。

于 2019-02-01T11:15:56.973 回答