[英]Counting Data inside of child controllers in Angular JS
我試圖圍繞AngularJS的工廠和服務保持頭腦,並不斷陷入困境。 這是一個與我要解決的問題類似的基本示例。
HTML
<div ng-controller="productGridController">
<div ng-repeat="category in categories" ng-controller="productCategoryController">
<input type="text" ng-model="category.name">
<div ng-repeat="product in products">
<input type="text" ng-model="product.name">
</div>
<a class="btn btn-small" ng-click="addProduct()">Add Product</a>
</div>
<a class="btn" ng-click="addCategory()">Add Category</a>
</div>
現在,假設我想獲得當前在根控制器productGridController
內實例化的所有產品的productGridController
,並將其存儲在變量中,我可以在productGridController
內部輸出變量,例如$scope.totalProducts
由於每個productCategoryController
都有自己的作用域,因此我不確定如何進行全局計數器和求和? 我認為服務或工廠可以做這樣的事情,但是我不確定如何實現。
我嘗試將根范圍變量放在productGridController
如下所示:
app.controller("productGridController", function($scope, $http, $rootScope, $timeout) {
$scope.totalProducts = 0;
$scope.categories = [];
$scope.addCategory = function() {
$scope.categories.push({name:''});
}
});
然后觀察productCategoryController
發生的任何更改
app.controller("productCategoryController", function($scope, $http, $rootScope, $timeout) {
$scope.products = [];
$scope.addProduct = function() {
$scope.products.push({name:''});
}
$scope.$watch('products', function() {
$scope.totalProducts = $scope.products.length;
}, true);
});
當僅添加一個類別時,此方法有效,但是當存在多個類別時,它僅考慮最近的一個類別。
還要記住,在我的實際應用程序中,我正在從數據庫中提取數據,因此這也需要能夠實時工作,因此可以隨時調用計數器功能以反映多少個產品的當前狀態。目前有。
在Angular JS中最簡單的方法是什么?
第一:
您正在監視“產品”。 當您在“ addProduct”中調用“ products.push()”時,product的值不變。 因此您的手表將不會被調用。 如果您改為說:
$scope.addProduct = function() {
$scope.products = $scope.products.concat([{name:''}]);
}
那么您的手表將按您的預期進行調用(因為“產品”的值已更改)。
第二:
不要忘記,您也可以使用$ watch的功能形式:
$scope.$watch(function() {return $scope.products.length;}, function() {
$scope.totalProducts = $scope.products.length;
});
但主要是:為什么要完全使用$ watch? 您可能已經說過:
$scope.addProduct = function() {
$scope.products.push({name:''});
$scope.totalProducts = $scope.products.length;
}
因為您知道這是一種副作用。
使用服務的想法是走得更遠,並將所有這些特定於數據的邏輯打包在一個地方,我們不必考慮如何以及何時呈現它。 然后,將該服務注入到控制器中,然后控制器(通過作用域)公開服務的相關部分。
當需要持久或共享狀態時,請實施工廠或服務來管理該狀態-這是有關差異(以及提供程序)的良好SO Q / A。
$ watch很不錯,但並不總是最好的選擇。 例如,如果您不能緩存產品數據集(可能很大),則通過$ broadcast更改事件可能是一個更好的選擇。
這是一個plnkr,通過一個產品服務來演示您的方案 ,該產品服務廣播一個添加/刪除操作的事件,以及一個偵聽該change事件並相應地更新其內容的指令。
ProductService的重要組成部分是在添加或刪除產品時對更改事件進行$ broadcasting:
app.service('ProductService', function($rootScope) {
let self = {
PRODUCT_COUNT_DELTA: "PRODUCT_COUNT_DELTA",
$inject: ['$rootScope']
}
// broadcast a PRODUCT_COUNT_DELTA event with the latest product count.
function changes(changeType) {
if (changeType == 0)
$rootScope.$broadcast(self.PRODUCT_COUNT_DELTA, self.getProductCount());
}
在演示中,添加或刪除產品時,服務方法addProduct和removeProduct調用內部更改功能。
指令productCount呈現當前產品計數並在收到產品計數更改通知時更新:
app.directive("productCount", ['ProductService', function(productService) {
let render = function(count) {
count = count || productService.getProductCount();
return "<span>" + count + "</span>";
}
return {
restrict: 'E',
template: function(elem, attr) {
return render();
},
link: function($scope, elem, attrs) {
$scope.$on(productService.PRODUCT_COUNT_DELTA, function($event, productCount) {
elem.html(render(productCount));
});
}
}
}]);
同樣,$ watch很方便,但並不總是正確的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.