如何从其父级访问嵌套组件的控制器?

How can I access the controller of a nested component from its parent?

我有三个 Angular 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 的选择中更新.

我的问题:

如何从 ReportFilter 的控制器内部调用 ClientSelectZoneSelect 组件的控制器上的 reset() 方法?

React 有一个 ref 标签,可让您访问控制器以调用其上的方法。

我认为首选方法是在您的子指令中添加一个名为 api:

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

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

然后当您调用该指令时,您只需传递一个范围属性:

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

您现在可以使用

从父控制器调用函数
$scope.foo.someFN()

没有 built-in 方式(不像 React,正如你提到的 :)

一个可能的解决方案是让 children 要求他们的 parent,并向其注册:

    // 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,
            ...
        };
    })

如果您想要children和parent组件之间的耦合,那么您可以重新设计children以便他们所有的数据,我的意思是所有,整个事情,都来自他们的 parent。在这种情况下,要重置 clientSelect,parent 控制器只需要清除与其共享的数据,即执行:

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