2016-08-04 116 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

相關問題