在另一个指令中要求指令的控制器

时间:2014-07-14 15:54:40

标签: javascript angularjs

我正在尝试通过他们的(内部定义的)控制器获得两个指令来相互通信,但我对角度很新,但仍然不清楚几件事情。

基本上,我只想要两个单独的指令,当你点击指令 A 中的一个元素时, B 中的一些函数会执行;我想根据 A 中的内容告诉 B 更新自己。到目前为止我得到了什么:

app.directive('A', function(){
    return{
        restrict: 'E',
        require:'B',
        templateUrl:'a.html',
        link: function(scope, element, attr, bController){
            //should I run B's behavior here?
            //how? can't reach B's controller
        },
        controller: function(){
            //or here?
            //how do I access B's controller here?
        },
        controllerAs:'A'
    };
});

app.directive('B', function(){
    return{
        restrict: 'E',
        templateUrl:'b.html',
        link: function(scope, element, attr){

        },
        controller: function(){
            //here there'll be functions that manipulate
            //elements inside this directive (B)
        },
        controllerAs:'B'
    };
});

我收到错误,因为 A 正在尝试找到名为 B 控制器,但它是一个指令:{{3 }}

另外,我应该操纵link函数或指令控制器中的元素吗?即使在阅读之后,我对link vs controller仍然有点模糊;我看待它的方式:link就像是各种构造函数,而控制器就是行为所在。

那么这是否意味着我总是将DOM操作放在控制器内部?

还有其他方法可以解决这个问题吗?我已经阅读了一些关于$scope的内容,但仍然不完全清楚。

2 个答案:

答案 0 :(得分:3)

您只能在父元素或同一元素中需要指令。你可能在A中使用B,反之亦然。

如果是这种情况,你有在另一个中使用的一个指令,你可以使用:require: '^A'转到内部指令并要求外部指令。 ^表示它可以是您父母的指示。

如果指令是兄弟姐妹,你可以构建一个第三个指令,将它们两者都包含在内,并且从两者内部都需要它,并且他们会使用这个媒介进行通信:

app.directive('C', function() {
  return {
    controller: function() {
      this.registerPartyA = function(partyA) {
        // ...
      };

      this.registerPartyB = function(partyB) {
        // ...
      };
    }
  }
});

然后从你的指令;

app.directive('B', function() {
  return {
    require: '^C',
    link: function(scope, elm, attr, cCtrl) {
      cCtrl.registerPartyB(...);

      // maybe when user clicks you do
      // cCtrl.aCtrl.doSomething()
    }
  };
});

如果它们无论如何,您仍然可以使用服务并在两个指令中注入服务,并将其用作常用位置。

最后,如果两个指令共享相同的范围(在同一个元素下,或者没有指令需要隔离/子范围),您可以直接在{{1}内部声明该方法并简单地从另一个指令中调用它:

$scope

最后一次通话,您可以使用$scope.$broadcast and $scope.$emit进行通信。

只要您符合要求,我就会按照我提及的顺序尝试

答案 1 :(得分:1)

来自控制器的AngularJS文档:

  

使用控制器:

     
      
  • 设置$ scope对象的初始状态。
  •   
  • 向$ scope对象添加行为。
  •   
     

请勿使用控制器:

     
      
  • 操纵DOM - 控制器应仅包含业务逻辑。   将任何表示逻辑放入控制器会显着影响   它的可测试性。 Angular对大多数情况和指令都有数据绑定   封装手动DOM操作。
  •   
  • 格式输入 - 改为使用角度形式控件。过滤器输出 - 改为使用角度过滤器。
  •   
  • 跨控制器共享代码或状态 - 改为使用角度服务。
  •   
  • 管理其他组件的生命周期(例如,创建   服务实例)。
  •   

从AngularJS文档中获取指令:

  

指令可以被认为是DOM元素上的标记(例如   告诉AngularJS的属性,元素名称,注释或CSS类   HTML编译器($ compile)将指定的行为附加到该DOM   元素甚至转换DOM元素及其子元素。

所以,只是为了清楚地说明,不应该从不操纵控制器内的DOM。您应该始终使用指令link函数来操作DOM。

如果您希望控制器彼此共享状态信息,则应考虑添加角度服务(文档here)。服务是一次实例化的对象,其状态在整个模块中保留。它们可以注入控制器。

另一种选择是实施一些$emit$on事件提升者和听众。这将允许您使用事件通过控制器进行通信,以指示状态更改。这是另一篇SO帖子,它比我更好地解释了这一点:Working with $scope.$emit and $scope.$on

希望这有帮助!