angular 指令能否将参数传递给指令属性中指定的表达式中的函数?

IT技术 javascript angularjs angularjs-directive angularjs-scope
2021-03-15 16:18:38

我有一个表单指令,它使用callback具有隔离范围的指定属性:

scope: { callback: '&' }

它位于 an 内部,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 游乐场在这里(打开控制台)。

5个回答

如果你像@lex82一样声明你的回调

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

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

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

不需要 $parse。查看我的小提琴(控制台日志)http://jsfiddle.net/k7czc/2/

更新文档中有一个小例子

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

这是一个很好的解决方案,谢谢你,但我相信答案需要一些调整。lex82 是谁,他提到了什么?
2021-04-21 16:18:38
有趣的方法。虽然当你想允许任何带有任何参数(或多个)参数的函数被传递时会发生什么?您对函数及其参数一无所知,并且需要在指令内部的某个事件上执行它。怎么办?例如,在指令上你可以有 onchangefunc='myCtrlFunc(dynamicVariableHere)'
2021-04-29 16:18:38
我不认为这是一个好的解决方案,因为在指令定义中,有时您不知道要传入的参数是什么。
2021-05-03 16:18:38
非常好!这在任何地方都有记录吗?
2021-05-14 16:18:38

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

在你的 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 的一篇优秀文章中改编了这种技术

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

一个不错的方法,但我无法this在回调方法中使用指针,因为它使用指令的范围。我正在使用 Typescript,我的回调如下所示:public validateFirstName(firstName: string, fieldName: string): ng.IPromise<boolean> { var deferred = this.mQService.defer<boolean>(); ... .then(() => deferred.resolve(true)) .catch((msg) => { deferred.reject(false); }); return deferred.promise; }
2021-05-03 16:18:38
注意:如果您有嵌套指令并希望向上传播回调,您需要在每个指令中解包,而不仅仅是一个触发回调。
2021-05-04 16:18:38

在指令 ( 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;
虽然有 In source: bound-function='myFunction(obj1.param, obj2.param)'> 那么如何进行?
2021-05-02 16:18:38

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

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

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

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

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

使用scope.$parent会使指令“泄漏”——它“知道”太多的外部世界,这是一个设计良好的封装组件不应该的。
2021-05-09 16:18:38
好吧,它知道它有一个父作用域,但它不访问作用域中的特定字段,所以我认为这是可以容忍的。
2021-05-13 16:18:38

对我来说以下工作:

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

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

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