在AngularJS中有两个自定义指令相互交互

时间:2014-07-04 07:19:50

标签: javascript angularjs angularjs-directive

我有两个指令

angular.module('myApp.directives', []).
            directive('exampleDirective', ['version', function(version) {
             return {
                      link:function(scope,elm,attr) {
                         elm.on('click',function() {
                              //access exampleDirective2 behaviour
                         });
                      }
                    }
            }]).
            directive('exampleDirective2', ['version', function(version) {
             return {
                      link:function(scope,elm,attr) {
                         elm.on('change',function() {
                              //access exampleDirective behaviour
                         });
                      }
                    }
            }]);

正如你在exampleDirective elm.on(click)函数中看到的那样,我希望得到exampleDirective2函数,反之亦然。

AngularJS有没有办法实现这个目标?

3 个答案:

答案 0 :(得分:2)

这个问题有三种解决方案:

第一个解决方案:使用服务

在包含数据和函数的指令之间共享服务。

.service('myService', function(){
    this.data = //....
    this.function = function() //...
})

.directive('dir1', ['myService', function(myService) {
   //...
   link: function(scope, elem, attrs) {
       scope.data = myService.data;
   }
}])

另一个指令也一样。

第二种解决方案:指令'控制器

如果您的指令具有父/子/兄弟关系:

.directive('dir1', function(){
    return {
        controller: function(scope, elem, attrs) {
            this.sayHello = function() {
                alert('hello')
            }
        }
    }
})

.directive('dir2', function(){
    return {
        require: '^dir1',
        link: function(scope, elem, attrs, dir1Ctrl) {
            dir1Ctrl.sayHello(); //will alert hello
        }
    }
})

但是,如果您的指令具有孤立的范围,那么这将不起作用。此外,根据指令(父/子或兄弟)的关系,require属性的sintax会略有变化;您可以在AngularJS docs上找到有关指令的更多信息。

第三种解决方案:使用事件

您也可以从指令范围发出/广播事件,或者注入$rootScope并将其用作事件总线:

.directive('dir1', function($rootScope){
    return {   
        link: function(scope, elem, attrs) {
           var emitEvent = function(){
               $rootScope.$emit('somethingHappenedEvent', { /*you can pass optional data*/ });
           }

           emitEvent();
       }
    }
})

.directive('dir2', function($rootScope) {
    return {
        link: function(scope, elem, attrs) {
            $rootScope.$on('somethingHappenedEvent', function(event) {
                if(!event.defaultPrevented) {
                    //react to event here
                }
            })      
        }
    }
})

您也可以使用普通scope代替$rootScope,但在这种情况下,您必须记住,事件会在所有范围内上下滑动(取决于使用$emit$broadcast)。我更倾向于从$emit $rootScope到它将是唯一能够捕捉事件的范围,并且也会非常快。

答案 1 :(得分:1)

执行此操作的一种方法是使用带有控制器的包装器指令,如果使用require,则可以在指令之间共享。一个更简单,也许更好的解决方案(因为它不依赖于DOM)是拥有一个通用服务,可以实现指令之间的通信。

答案 2 :(得分:1)

如果您只想以指令方式执行此操作。 这是答案

angular.module('myApp.directives', []).
        directive('exampleDirective', ['version', function(version) {
         return {
                  link:function(scope,elm,attr) {
                     elm.on('click',function() {
                          //access exampleDirective2 behaviour
                          scope.exampleDirective2Function();
                     });
                     scope.exampleDirectiveFunction = function (){
                          //write your code here
                     }
                  }
                }
        }]).
        directive('exampleDirective2', ['version', function(version) {
         return {
                  link:function(scope,elm,attr) {
                     elm.on('change',function() {
                          //access exampleDirective behaviour
                          scope.exampleDirectiveFunction();
                     });
                     scope.exampleDirective2Function= function (){
                          //write your code here
                     }
                  }
                }
        }]);

另一种方法是,您可以编写服务,在其中编写函数,并通过将服务注入指令来使用该服务函数。