簡體   English   中英

在Angular JS中對子控制器內部的數據進行計數

[英]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());
  }

在演示中,添加或刪除產品時,服務方法addProductremoveProduct調用內部更改功能。

指令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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM