角度指令可以将参数传递给指令属性中指定的表达式中的函数吗?

时间:2013-11-10 12:20:45

标签: javascript angularjs angularjs-directive angularjs-scope

我有一个表单指令,它使用带有隔离范围的指定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(打开控制台)。

5 个答案:

答案 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>

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