angularjs - 如何在AngularJS的递归指令中传递函数引用?

标签 angularjs angularjs-directive

我有这个指令:

app.directive('recursiveListItem', ['$http', 'RecursionHelper', function ($http, RecursionHelper) {
    return {
        restrict: 'E',
        scope: {
            parent: '=',
            onNodeClick: '&',
        },
        compile: function (element, attributes) {
            return RecursionHelper.compile(element);
        },
        template:
            '<div class="list-group-item-heading text-muted parent "> \
                <input type="checkbox" data-ng-click="visible = !visible" id="{{parent.Name}}">\
                <label for="{{parent.Name}}">&nbsp;&nbsp;</label>\
                <a href="javascript:void(0)" data-ng-click="onNodeClick({node: parent})">{{parent.Name}}</a> \
            </div> \
            <ul data-ng-if="parent.Children.length > 0" data-ng-show="visible"> \
                <li ng-repeat="child in parent.Children"> \
                    <recursive-list-item data-parent="child" data-on-node-click="onNodeClick"></recursive-list-item> \
                </li> \
            </ul>',     
    };
}]);

这是 helper :
app.factory('RecursionHelper', ['$compile', function ($compile) {
    var RecursionHelper = {
        compile: function (element) {
            var contents = element.contents().remove();
            var compiledContents;
            return function (scope, element) {
                if (!compiledContents) {
                    compiledContents = $compile(contents);
                }
                compiledContents(scope, function (clone) {
                    element.append(clone);
                });
            };
        }
    };

    return RecursionHelper;
}]);

一切都像一个咒语,但我的on-node-click无法正常工作。对于所有的根项目,“回调”都可以正常工作,但是从那以后,所有子级都不会触发回调。我认为这与将函数引用传递给模板中的下一个 child 有关。

我也尝试过data-on-node-click="onNodeClick(node)",但这也不起作用。

有人知道如何将函数引用传递给子节点吗?

最佳答案

潜在问题

作为引导,有助于查看docs用这种方式描述的“&”:

& or &attr - provides a way to execute an expression in the context of the parent scope.

Often it's desirable to pass data from the isolated scope via an expression and to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22})



为了实现此目的,将通过&传递的函数包装在另一个函数parentGet()中。通过查看点击处理程序函数变量的内容,我们可以看到这一点。首先,在将其传递到&之前,它与我们期望的一样:
function (node) {
    console.log("called with ",node);
} 

但是,然后,在您的指令中,在通过'&'之后,它看起来像这样:
function (locals) {
     return parentGet(scope, locals);
} 

因此,现在不再是直接引用您的单击处理程序函数,而是一个调用,它将使用父作用域和您在中传递的任何locals来应用您的函数。

问题是,据我所知,随着我们嵌套该范围变量,不断将更新为新的嵌套父范围。这对我们不利。我们希望执行上下文成为您的点击处理程序所在的顶级范围。否则,我们会失去对您功能的引用-正如我们所看到的那样。

解决方案

为了解决这个问题,我们保留了对原始函数的引用(当我们嵌套时,它不受parentGet()的约束)。然后,当我们传递它时,parentGet()中使用的作用域就是带有单击处理程序功能的作用域。

首先,让我们对实际函数使用与对参数使用不同的名称。我像$scope.onNodeClickFn = function(node) {...}这样设置功能

然后我们进行3处更改:

1)添加第二个作用域变量(topFunc):
scope: {
          onNodeClick: '&',
          topFunc: '='
       }
onNodeClick是包装的函数(包括范围参数)。 topFunc是对未包装函数的引用(请注意,我们在使用=时对此进行了传递,因此它是对没有&应用的包装器的函数的引用)。

2)在顶层,我们传入两个函数引用。
<recursive-list-item on-node-click="onNodeClickFn(node)" top-func="onNodeClickFn" parent=parent ></recursive-list-item>

(请注意top-func参数上缺少()。)

3)将新的topFunc参数传递到模板中:
<recursive-list-item data-parent="child" data-on-node-click="topFunc(node)" top-func="topFunc"></recursive-list-item> \

因此,我们现在在每个嵌套范围内维护对原始函数的引用,并在模板中使用该引用。

您可以看到它在这个 fiddle 中起作用:http://jsfiddle.net/uf6Dn/9/

关于angularjs - 如何在AngularJS的递归指令中传递函数引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20073305/

相关文章:

javascript - 重复级联选择选项

javascript - 更改 AngularJS 中特定标题的颜色

javascript - 插入商店时如何收到错误?

javascript比较两个数组找出不同之处

javascript - Angular 如何通过单击 div 来检查复选框

javascript - $parsers-array 中的函数未在自定义指令中调用

java - Spring MVC 作为 REST 提供者,AngularJS 与 Web 层的 JSP/Velocity/Freemarker

javascript - 无法选择 iframe 内的元素

angularjs - 从一组编辑器中删除 tinymce 4 编辑器

javascript - AngularJS 指令、范围、魔法和重复模板