angularjs多个嵌套的父子指令通信

时间:2015-01-25 22:36:08

标签: angularjs angularjs-directive angularjs-scope angularjs-controller

我有一个包含子指令的指令,该指令也包含一个子指令,我试图使用最顶层的父控制器来访问孙子的控制器并调用一个属于孙子控制器的函数。函数未定义时出错。我希望能够通过孙子控制器使用最顶层的父级来控制孙子指令。

angular.module('components', [])
.controller('MyButtonController', ['$scope', function($scope){
    this.mySubButtons = [];
    
    this.addSubButtons = function(s){
        this.mySubButtons.push(s);
    }
    
}]).controller('MyButtonGroupController', ['$scope', function($scope){
    this.myButtons = [];
    this.addMyButtonCtrl = function(ctrl){
        this.myButtons.push(ctrl);
    };
    this.setName = function(name){
        //undefined function
        this.myButtons[0].setName(name);
        console.log(this.myButtons);
    }
}])
.directive('mySubButton', function(){
    return {
        restrict: 'E',
        scope:{}, 
        require: ['^myButton', 'mySubButton'],
        template: '<div>Hello {{name}}</div>',
        controller: ['$scope', function($scope){
            $scope.name="phil";
            this.setName = function(name){
                $scope.name = name;
            }
        }],
        link: function(scope,element,attrs, ctrls){
            ctrls[0].addSubButtons(ctrls[1]);
        }
    }
})
.directive('myButton', function () {
        return {
            restrict: 'E',
            scope:{},
            require: ['^myButtonGroup','myButton'],
            controller: 'MyButtonController',
            template: '<div><my-sub-button></my-sub-button><my-sub-button></my-sub-button></div>',
            link: function(scope,element,attrs, ctrls){
                ctrls[0].addMyButtonCtrl(ctrls[1]);
            }
        }
    })
.directive('myButtonGroup', function(){
    return {
        restrict:'E',
        scope:{},
        transclude: true,
        replace: true,
        controller: 'MyButtonGroupController',
        template: '<div ng-transclude></div>',
        link: function(scope,element, attrs, groupCtrl){
            var myButtonsCtrls = groupCtrl.myButtons;
            groupCtrl.setName('Jill');
          
        }
    }
})

angular.module('HelloApp', ['components'])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body  ng-app="HelloApp">
    <my-button-group>
        <my-button></my-button>
        <my-button></my-button>
    </my-button-group>
</body>

jsfiddle链接:http://jsfiddle.net/jaLhwgbg/2/

2 个答案:

答案 0 :(得分:0)

使用事件代替,您将获得更清晰的代码。动态修改代码时,您永远无法确定函数或属性是否存在。通过事件,您只需提醒其他人采取行动,以便他们认为合适。

所以MyButtonController会$scope.$broadcast('doSomethingMyButtonChildren')而你的mySubButton指令会采取像scope.$on('doSomethingMyButtonChilden', function() {})这样的行动。

以上是更清晰,更易读,更易于测试的代码的最佳实践。但是,要回答您的原始问题,您的addMyButtonCtrl函数会出现上下文问题。

错误

this.mySubButtons = [];
this.addMyButtonCtrl = function(ctrl){
    this.mySubButtons.push(ctrl);
    // 'this' is refering to the closure of the function addMyButtonCtrl
    // not of the controller itself
};

正确

this.mySubButtons = [];
this.addMyButtonCtrl = function(ctrl){
    mySubButtons.push(ctrl);
};

答案 1 :(得分:0)

您没有在MyButtonController中定义setName,这是您尝试调用setName的类型。

http://jsfiddle.net/y2vfhzwe/

MyButtonController成为:

.controller('MyButtonController', ['$scope', function($scope){
    this.mySubButtons = [];

    this.addSubButtons = function(s){
        this.mySubButtons.push(s);
    }
    this.setName = function(name) {
        this.mySubButtons[0].name = name;
    }