2016-09-17 49 views
2

我有一個子組件MyStats,它將輸入數據作爲列表並顯示關於該列表的統計信息。當myData中的列表更新時,我需要在組件內調用rebuildStats函數。由於組件中沒有$ scope,所以我不能添加$ watch。有沒有辦法從MainCtrl調用rebuildStats?什麼是解決它的最好方法?如何訪問Angular1.5中父控制器的組件方法

module.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) { 
    $scope.statData = {}; 
    $http.get('..some url..').then(function(resp) { 
    $scope.statData.list = resp.list; 
    }); 
}]); 

module.component('myStats', { 
    'templateUrl': '...', 
    'bindings': { 
     'myData': '<ngModel' 
    }, 
    'controller': function() { 
     this.totalActive = 0; 
     this.rebuildStats = function() { 
     var cntr = 0; 
     angular.forEach(this.myData.list, function (item) { 
      if (item.isActive) { 
      cntr++; 
      } 
     }); 
     this.totalActive = cntr; 
     }; 

    } 
}); 

<my-stats ng-model="statData"></my-stats> 

編輯:有2個解決方案,我現在使用: 1)在數據塊I改變爲2路結合和介紹了從組件內創建,然後父母可以調用此setter函數功能。它不使用$範圍,但仍...不知道這是什麼角度的創作者的意圖。

module.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) { 
    $scope.statData = {}; 
    $http.get('..some url..').then(function(resp) { 
    $scope.statData.setList(resp.list); 
    }); 
}]); 

module.component('myStats', { 
    'templateUrl': '...', 
    'bindings': { 
     'myData': '=ngModel' 
    }, 
    'controller': function() { 
     var ctrl = this; 

     this.totalActive = 0; 
     this.rebuildStats = function() { 
     var cntr = 0; 
     angular.forEach(ctrl.myData.list, function (item) { 
      if (item.isActive) { 
      cntr++; 
      } 
     }); 
     ctrl.totalActive = cntr; 
     }; 
     this.myData.setList = function (list) { 
     ctrl.myData.list = list; 
     ctrl.rebuildStats(); 
     }; 
    } 
}); 

第二種方法是通過元件訪問控制器。像這樣:

var getController = function(elementSelector, controllerName) { 
     var el = angular.element(document.querySelector(elementSelector)); 
     if (el) { 
     return el.controller(controllerName); 
     } 
     return null; 
    }; 

所以,現在如果我有MyTestController控制器,具有標籤「我的測試控制器」和具有ID =「ID1」那麼我可以訪問它想:

var ctrl = getController('my-test-controller#id1', 'MyTestController'); 
ctrl.MyTestControllerMethod(); // access any exposed method 

回答

0

如果認爲使用ES2015 getter/setter語法將是最佳解決方案。

class MyStats{ 
    get myData() { 
     return this.$value; 
    } 
    set myData(value) { 
     this.$value = value; 
     this.rebuildStats(); 
    } 

    ... 
} 


module.component('myStats', { 
    'templateUrl': '...', 
    'bindings': { 
     'myData': '<ngModel' 
    }, 
    'controller': MyStats 
}); 

或者只是注入$範圍,以你的位指示功能與$注入語法:

MyStatsController.$inject = ['$scope']; 
function MyStatsController($scope) { 
    ... 
} 
+0

我必須在舊的ES5領域進行操作。我可以$注入,但這聽起來很駭人(因爲從組件中取出$ scope是有原因的)。我覺得很奇怪,我可以使用像'onUpdate'這樣的函數綁定從組件到父組通信:'&',但是沒有明顯的方法(如果有的話)從父組件調用。 –

0

這很奇怪有一個與「現代」的組件和單向數據綁定混合了經典控制器+範圍。

首先想到的是,你需要你的組件來調用服務本身。您不需要外部控制器和綁定。

var vm = this; 
this.$onInit = function() { 
    $http.get(...).then(function() { vm.rebuildStats(); }) 
} 

更好的是,把這個邏輯放到一個服務中,然後調用$ onInit中的服務。 當承諾解決並且您的數據已準備就緒時,請致電您的功能。

這樣你就有了一個完全獨立的組件,你的代碼變得更輕,更好。

如果你真的需要傳遞一個屬性裏面的數據,你可以使用$ onChanges檢查模型的變化:

var vm = this; 
this.$onChanges = function (changes) { 
    if (changes.myData) { 
    vm.myData= angular.copy(changes.myData.currentValue); 
    vm.rebuilsStats(); 
    } 
}; 
+0

該組件將用於來自不同控制器的數據分析:用戶評論的統計數據,評論和書評。由於其非常通用,我不能將它綁定到特定的數據源。所以在這方面數據必須作爲參數傳遞。我嘗試了$ onChanges,但它只在組件合併期間調用,並且在從$ http更新列表時不會調用 –

+1

不,這是錯誤的,它在綁定數據更改時調用。 https://toddmotto.com/angular-1-5-lifecycle-hooks#onchanges – gyc

0

我也有類似的問題,這樣的事情爲我工作:

var scope = $('my-stats').children().scope(); 
scope.$ctrl.rebuildStats(); 

$('my-stats').scope()是組件的「外」的範圍,你必須調用children()得到「內部」(只要有任何子女)。

雖然我不認爲這是正確的方法。文檔說scope()只是用於調試。

相關問題