2016-08-04 80 views
1

我有三个角1.5组件:ReportFilterClientSelectZoneSelect如何从父级访问嵌套组件的控制器?

ReportFilter具有它内部的两个部件

<!-- Report Filter --> 
<div> 
    <client-select client="$ctrl.selections.client"></client-select> 
    <zone-select zone="$ctrl.selections.zone"></zone-select> 
    <button ng-click="$ctrl.search()">Get Report</button> 
    <button ng-click="$ctrl.clear()">Clear</button> 
</div> 

clientzone是双向数据绑定,从而当用户选择了一个客户端或一个区域,相应的性能列于我的ReportFilter更新'的选择。

我的问题:

我怎么能说我的ClientSelectZoneSelect组件的控制器上的reset()方法从ReportFilter的控制器里面?

阵营有ref标签,可以让你访问控制器调用它的方法。

回答

1

我相信采取首选的方法是在你的孩子的指令,你可以添加一个scope属性调用的API:

app.directive('childDirective', function() { 
    return { 
    scope: { 
     api: "=?" 
    }, 
    link: function(scope, elem, attrs) { 
     return { 
     scope.someFN = function() { 
      // do stuff. 
     }; 

     scope.api = { 
     someFN: scope.someFN 
     }; 
     }; 
    }; 
    }; 
}); 

然后当你调用指令,你简单地传递一个scope属性:

<div ng-controller="parentCtrl"> 
    <child-directive api="foo"></child-directive> 
</div> 

,现在您可以打电话从父控制器的功能与

$scope.foo.someFN() 
+0

我见过几个其他组件(如UI-网格)使用此方法,因为好。 – sflogen

+0

我注意到一些库的一些奇怪的行为,例如angular-nvd3通常需要你提供一个'on-ready'函数来实际填充范围变量。 – aaronmallen

+0

我不确定这是否是预期的行为,但是因为angular-nvd3也允许你定义api,但它似乎并没有实际填充变量,除非你在准备就绪的函数中这样做。 – aaronmallen

2

ŧ这里是没有内置的方式(不像反应,你提到:)

一个可能的解决方案是让孩子需要他们的父母,并注册自己吧:

// child directive 
    .directive('clientSelect', function() { // `.component` is similar... 
     return { 
      ... 
      controller: ClientSelect, 
      require: ['clientSelect', 'reportFilter'], 
      link: function(scope, elem, attrs, ctrls) { 
       ctrls[1].setClientSelect(ctrls[0]); 
       // do not forget to deregister, just in case 
       scope.$on('$destroy', function() { 
        ctrls[1].setClientSelect(null); 
       }); 
      } 
     }; 
    }) 

    // parent directive 
    .directive('reportFilter', function() { 
     function ReportFilter() { 
      ... 
     } 

     ReportFilter.prototype.setClientSelect = function(clientSelect) { 
      this.clientSelect = clientSelect; 
     }; 

     ReportFilter.prototype.somethingElse = function() { 
      // reset the clientSelect: 
      this.clientSelect.reset(); 
     }; 

     return { 
      ... 
      controller: ReportFilter, 
      ... 
     }; 
    }) 

如果你不想要孩子和父母组件之间的耦合,那么你可以重新设计孩子,使他们的所有数据,我的意思是所有,整个事情,都来自父母。在这种情况下,重置clientSelect,父控制器只需要清除它与它共享数据,即做到:

// in the parent controller 
this.selections.client = {}; // or null or... 
+0

我喜欢这种方法,除了指令现在具有对特定控制器的依赖关系之外。 – aaronmallen

+1

如果指令是独立组件,这种耦合确实很糟糕。但是,如果他们打算从可用性的角度一起工作,那不是。例如。树中的节点总是树的一部分。要求他们的父“树”组件不会导致更多的耦合。 –

+0

这个想法_could_ work,但我打算在'ReportFilter'之外的其他地方使用'clientSelect'和'reportFiler'组件。 – sflogen

相关问题