4

我开发了一个经典的递归菜单,它自己构建得很好。问题是 ngClick 永远不会从递归指令的元素中触发。我知道这是范围的问题,我尝试了很多配置,但没有运气。

这是一个小提琴:http: //jsfiddle.net/PM2dy/2/

要调用的函数是retrieveFiles(path)

和代码:

app.directive("mediaTree", function ($compile) {
    return {
        restrict: "E",
        scope: { folder: '=', retrieveFiles: '=' },
        template:
            '<ul>' +
                '<li data-ng-repeat="child in folder.Children">' +
                    '<a href="#" data-ng-click="retrieveFiles(child.Path)">{{child.Name}}</a>' +
                    '<media-tree folder="child"></media-tree>' +
                '</li>' +
            '</ul>',
        compile: function (tElement, tAttr) {
            var contents = tElement.contents().remove();
            var compiledContents;
            return function (scope, iElement, iAttr) {
                if (!compiledContents) {
                    compiledContents = $compile(contents);
                }
                compiledContents(scope, function (clone, scope) {
                    iElement.append(clone);
                });
            };
        }
    };
});


app.directive('mediaPanel', function ($compile) {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function (scope, elem, attrs) {
            scope.retrieveFiles = function (me) {
                console.log("thanks for calling " + me);
            }
            scope.folder = {
                Name: 'Media',
                Path: '/',
                Children: [
                    {
                        Name: 'Child1',
                        Path: '/Child1',
                        Children: [
                            {
                                Name: 'GrandChild1',
                                Path: '/Child1/GrandChild1',
                                Children: []
                            }
                        ]
                    },
                    {
                        Name: 'Child2',
                        Path: '/Child2',
                        Children: [
                            {
                                Name: 'GrandChild2',
                                Path: '/Child1/GrandChild2',
                                Children: []
                            }
                        ]
                    }
                ]
            };

            elem.append($compile("<media-tree class='media-tree' folder='folder'></media-tree>")(scope));            
        }
    }
});
4

1 回答 1

3

The method I use in such cases is the "require controller of parent directive". In the mediaTree directive, add:

require: "^mediaPanel"

Now all the mediaTree nodes have access to the controller of mediaPanel. Write one, exposing the function you want to be called (NOTE: Using this, not $scope):

app.directive('mediaPanel', function ($compile) {
    ...
    controller: function($scope) {
        this.retrieveFiles = function(me) {
            console.log("thanks for calling " + me);
        };
    }
});

Then the link function of the mediaTree has access to this controller and its retrieveFiles member:

compile: function (tElement, tAttr) {
    ...
    return function (scope, iElement, iAttr, mediaPanel) {
        // call mediaPanel.retrieveFiles(x) from here, or put it in scope
    };
}

I took some liberty and re-arranged your code a bit. Some compilations were not really needed, I moved the data definition to a top-level controller etc. See fiddle with re-arrangements and the working case: http://jsfiddle.net/KRDEf/

于 2013-10-16T11:27:46.763 回答