从子指令调用指令函数不起作用

时间:2016-03-13 21:29:57

标签: javascript angularjs angularjs-directive angularjs-scope

我正在尝试使用其他人创建的指令来告诉我的指令何时其中的ngRepeat已经完成了自己的创建。

我的外部指令有一个隔离范围,并且有一个范围函数,需要由内部指令调用。这是代码。

angular.module('my.directives')

.controller('myTableCtrl', function($scope, $element, $attrs) {

    $scope.tableLoaded = function(tableName){
        console.log("Table Loaded");
    };

})

.directive('myTable', function() {
    return {
        restrict: 'EA',
        scope: {},
        controller: 'myTableCtrl as myTable'
    };
})

.directive('repeatDone', function($timeout) {
    return function(scope, element, attrs) {
        if (scope.$last) {
            $timeout(function(){
                scope.$eval(attrs.repeatDone);
            });
        }
    }
});

我的HTML看起来像这样。

<my-table>
    <div ng-repeat="row in tableRows" repeat-done="tableLoaded('main');"></div>
</my-table>

在我将范围:{}添加到myTable指令之前,当页面上有多个表(tableLoaded函数被调用但被错误的子进程调用)时,它变得非常困惑,所以我添加了隔离范围,我认为是最好的做法。不幸的是,repeatDone指令现在无法在父myTable指令中看到/调用tableLoaded()函数。

任何帮助都会非常感激。

编辑:

只是澄清一下。 tableLoaded()是myTable指令的一个函数,我希望能够从repeatDone指令调用它,但是这可能是table指令内部的元素。除此之外,我不想更改repeatDone指令,而且repeatDone也不需要甚至不知道myTable指令。

2 个答案:

答案 0 :(得分:1)

请查看以下解决方案。希望这会有所帮助:)

    angular.module('my.directives')

    .controller('myTableCtrl', function($scope, $element, $attrs) {

    this.tableLoaded = function(tableName){    //bind the function to controller rather than $scope
        console.log("Table Loaded");
    };

    })

    .directive('myTable', function() {
    return {
        restrict: 'EA',
        scope: {},
        controller: 'myTableCtrl as myTable'
    };
})

.directive('repeatDone', function($timeout) {
    return {
        restrict: 'EA',
        scope: true,  //your child directive might want to inherit stuff from the parent directive's controller maybe 
        require:'?^myTable',  //require the parent directive 
        link: function(scope, element, attrs,tableCtrl) {  //the controller of myTable is available as 4th param in link function (because of require)
            if (scope.$last) {
                $timeout(function(){
                    //scope.$eval(attrs.repeatDone);
                    tableCtrl.tableLoaded();    //call the function of the parent's directive (the specific instance)
                });
            }
        }
    }
});

修改

我想到的问题是一次拥有多个表,每个表中都有一个repeatDone。 您可以做的是,您可以在完成范围后发出事件并将其捕获到您所需的控制器/指令中。或者,您也可以传递唯一标识符,以便仅在特定控制器/指令内捕获。 这是一个例子:

.directive('repeatDone', function($timeout) {
    return {
        restrict: 'EA',
        link: function(scope, element, attrs) {
          console.log('in directive');
            var targetUID = attrs.target;
          console.log(targetUID);
            if (scope.$last) {
                $timeout(function(){

                  console.log('repeat-done now');//scope.$eval(attrs.repeatDone);
                    scope.$emit('repeat-done-' + targetUID,{});
                });
            }
        }
    };
});
表指令中的

.directive('myTable', function() {
    return {
        restrict: 'EA',
        controller: 'myTableCtrl as myTable'
    };
})

并在您的表格控制器中:

.controller('myTableCtrl', function($scope, $element, $attrs) {
    console.log('in table Ctrl');
            var self = this;
            $scope.tableUID = $attrs.tableId;
            self.tableLoaded = function(){
                console.log("Table Loaded");
            };
            console.log('tableUID' + $scope.tableUID);
            $scope.$on('repeat-done-' + $scope.tableUID, function(event,args){
              console.log('in catcher function');
                self.tableLoaded();
            });
})

然后使用

<my-table table-id="table1">
    <div ng-repeat="row in tableRows" repeat-done target="table1"></div>
</my-table>

这是一个有效的JSBIN

希望这有帮助

答案 1 :(得分:0)

我认为您可能需要在my-table上使用ng-transclude才能使用内部元素