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

如何在AngularJS的递归指令中传递函数引用?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有这个指示: app.directive('recursiveListItem', ['$http', 'RecursionHelper', function ($http, RecursionHelper) { return { restrict: 'E', scope: { parent: '=', onNodeClick: '&', }, compile: fu

我有这个指示:

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>',     
    };
}]);
每件事都像一个符咒,但我没有让我的
在节点上点击
工作。对于所有根项目,“回调”工作正常,但从那时起,所有子项都不会启动回调。我认为这与将函数引用传递给模板中的下一个子级有关

我还尝试了在node click=“onNodeClick(node)”
上使用数据,但这也不起作用

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

根本问题 作为一个有助于了解“&”的导语,该词是这样描述的:

&or&attr-提供在的上下文中执行表达式的方法 父范围

通常需要通过 表达式和父作用域,这可以通过传递映射来完成 将局部变量名称和值的。对于 例如,如果表达式是increment(amount),那么我们可以指定 通过将localFn调用为localFn({amount:22})的amount值

为了实现这一点,通过
&
传递的函数被包装在另一个函数
parentGet()
中。通过查看click handler函数变量的内容,我们可以看到这一点。首先,在它被传递到
之前,正如我们所期望的:

function (node) {
    console.log("called with ",node);
} 
但是,在您的指令中,在通过“&”之后,它看起来是这样的:

function (locals) {
     return parentGet(scope, locals);
} 
因此,不再直接引用click handler函数,而是使用父作用域和传入的任何
局部变量来应用函数的调用

问题是,据我所知,当我们嵌套范围变量时,会不断更新到新的嵌套父范围。那对我们不好。我们希望执行上下文是单击处理程序所在的顶级作用域。否则我们就失去了对你函数的引用——正如我们所看到的那样

解决方案 为了解决这个问题,我们保留了对原始函数的引用(当我们嵌套时,它不会受到
parentGet()
的阻碍)。然后,当我们传入它时,
parentGet()
中使用的作用域就是带有click handler函数的作用域

首先,让我们为实际函数使用与参数不同的名称。我将函数设置为so
$scope.onNodeClickFn=function(node){…}

然后我们做3个改变:

1)添加第二个范围变量(
topFunc
):

onNodeClick
是包装函数(包括范围参数)。而
topFunc
是对unwrapped函数的引用(请注意,我们在使用
=
时传递了它,因此它是对
&
应用的没有包装的函数的引用)

2)在顶层,我们传入两个函数引用

<recursive-list-item on-node-click="onNodeClickFn(node)" top-func="onNodeClickFn" parent=parent ></recursive-list-item>
因此,我们现在在每个嵌套范围中维护对原始函数的引用,并在模板中使用该引用


你可以看到它在这把小提琴中工作:

我只是用一个调查问卷应用程序做了同样的事情,我保持函数在各个级别的隔离范围内传递的方式是将函数放在函数({param:param})符号中的每个项中

在您的应用程序中,也可以是:

 <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({param:param})"></recursive-list-item> \
            </li> \
        </ul>',  
在指令控制器中,您也可以调用它:

onNodeClick({param1: value1, param2:value2})

否则,如果onNodeClick仅影响主控制器(添加指令的页面)中的变量,则可以将主控制器作用域中存在参数的函数名传递给指令,并在指令控制器中不使用参数的情况下使用该函数。

Thanx了解解决方案和解释。然而,我必须说,我发现很难理解到底发生了什么(“&”部分,为什么要更改函数名,为什么要使用
scope.&parent
),我的解释不是最好的。我已经更新了,所以我希望它更清晰一点。
&
的工作方式相当棘手。如果有帮助,
scope.onNodeClickFn=scope.$parent.onNodeClickFn
只需将
onNodeClickFn
的副本一直放在当前作用域上(将父作用域上的副本复制到当前嵌套作用域)。感谢您的更新答案,不胜感激。尽管如此,这仍然是一件困难的事情:)@b1r3k这是你的plunker更新了:原来的JSFIDLE似乎不再工作了。onNodeClickFn中的console.log命令不会激发。
<recursive-list-item data-parent="child" data-on-node-click="topFunc(node)" top-func="topFunc"></recursive-list-item> \
 <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({param:param})"></recursive-list-item> \
            </li> \
        </ul>',  
on-node-click="onNodeClick(param1,param2)"
onNodeClick({param1: value1, param2:value2})