在调用api函数之前等待内部指令编译

时间:2015-11-30 14:54:40

标签: javascript angularjs angularjs-directive

我遵循以下模式,我需要从父指令调用子指令的API函数

以下是小提琴:http://jsfiddle.net/gauravsoni/qykbfvy0/2/

var myApp = angular.module('myApp',[]);

myApp.controller('MyCtrl',function(){

})

myApp.directive('d1', function() {
    return {
        controller: function($scope,$element) {
            console.log('d1 - ctrl');
          // $scope.api.awesomeApi();
            $scope.clicked = function(){
                $scope.api.awesomeApi();
            }
        },
        link: function(scope,ele,attr) {
           //scope.api.awesomeApi();
           console.log('d2 - link');
        },
        template:"This is D1<button ng-click='clicked()'>Clicked</button> <div d2 apifn='api'></div>"
    }
});
myApp.directive('d2', function() {
    return {
        scope:{
            apifn:"="
        },
        controller: function($scope,$element) {
           console.log('d2 - ctrl');
           $scope.isvisible = true;
           function awesomeApiFn(){
            console.log('api function is called');
           }
           $scope.apifn = {
            awesomeApi:awesomeApiFn
           } 
        },
        link: function(scope,ele,attr) {
          console.log('d2 - link');
        },
        template:'<div ng-if="isvisible"><p>Hello</p><h3>WORLD</h3><div>'
    }
});

问题是当我在加载d1控制器期间调用$scope.api.awesomeApi()时它显示未定义哪个是正确的,但是当我在d1的链接中调用awesomeApi()时它应该作为d1的链接工作在d2的链接之后被调用但它不起作用并且我再次未定义。

如何确保d1中的api函数仅在d2完成编译后调用?或者是否有一些更好的模式来揭示指令d2的API函数。

1 个答案:

答案 0 :(得分:0)

考虑将d1控制器注入child指令并在链接阶段(example fiddle)添加api对象:

myApp.directive('d1', function() {
    return {
        controller: function($scope,$element) {
            var self = this;
            console.log('d1 - ctrl');
            $scope.clicked = function(){
                self.api.awesomeApi();
            }
        },
        // ctrl.api has been set by child directive's link function
        link: function(scope,ele,attr,ctrl) {
           console.log('d1 - link');
           ctrl.api.awesomeApi();
        },
        template:"This is D1<button ng-click='clicked()'>Clicked</button> <div d2></div>"
    }
});

myApp.directive('d2', function() {
    return {
        // require both controllers
        require: ['^d1', 'd2'],
        controller: function($scope,$element) {
           console.log('d2 - ctrl');
           $scope.isvisible = true;
           function awesomeApiFn(){
            console.log('api function is called');
           }
           // put api object on d2 (this) controller
           this.api = {
            awesomeApi:awesomeApiFn
           } 
        },
        link: function(scope,ele,attr,ctrls) {
          var d1Controller = ctrls[0];
          var d2Controller = ctrls[1];
          console.log('d2 - link');
          // update d1Controller to have d2Controller api
          d1Controller.api = d2Controller.api;
        },
        template:'<div ng-if="isvisible"><p>Hello</p><h3>WORLD</h3><div>'
    }
});

我认为您遇到的问题是,由于来自隔离范围的2路绑定,$ scope.api对象直到另一个摘要周期才被修改。从父控制器到子控制器进行通信的另一个选择是$从父作用域广播事件。子范围将处理此问题并委托其api函数。为您的用例做最有意义的事情。如果d1和d2相互依赖,可能需要使用控制器注入(例如上面的例子)。如果你想让它们更松散地耦合,那么请选择事件。从您的示例中看,它们似乎属于一起(因为您正在访问两者之间的对象)。