Рассчитать общее количество повторных сумм товаров в корзине с угловым

У меня есть упрощенная корзина для покупок, подобная следующей, с контроллером для каждого элемента корзины:

<!DOCTYPE HTML>
<html ng-app="cart">
  <div ng-controller="cartCtrl">
    <table>
      <tr><th>qty</th><th>prize</th><th>total</th></tr>
      <tr ng-repeat="item in cartItems" ng-controller="cartItemCtrl">
        <td>
          <input ng-model="item.qty"/>
        </td>
        <td>
          <input ng-model="item.prize" />
        </td>
        <td>
          {{total}}
        </td>
      </tr>
     </table>
     total: {{cartTotal}}
   </div>

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.js"></script>
  <script>
(function(){

var cart = angular.module('cart', []);

cart.controller('cartCtrl', ['$scope', function($scope){
  $scope.cartItems = [{},{},{},{}];
}]);

cart.controller('cartItemCtrl', ['$scope', function($scope){

  $scope.$watchCollection('item', function(){
    $scope.total = $scope.item.qty * $scope.item.prize;
  });
}]);

}());
  </script>
</html>

Я не смог заставить это работать в JSFiddle: http://jsfiddle.net/XY3n8/1/

Теперь я хочу рассчитать общую сумму корзины, но я не хочу пересчитывать итоговые суммы товаров. Вместо этого я хочу повторно использовать уже рассчитанные итоги элементов. Как? (В моем случае расчет общего количества предметов немного сложнее.)


person Thomas Koch    schedule 24.11.2013    source источник


Ответы (2)


Вам нужно сделать «глубокое» наблюдение за коллекцией и объектом, чтобы получить промежуточные итоги и итоги. $watchCollection лучше знать, когда что-то добавляется/удаляется. $watch будет искать изменения в существующих объектах.

Для инкапсуляции общего элемента есть несколько способов сделать это, но я бы, вероятно, создал модель Item (вероятно, лучшее имя) и внедрил бы ее через factory. Это устраняет необходимость в одном из контроллеров в этом примере, но требует создания модуля (что в любом случае является наилучшей практикой).

Как насчет этого?

var ShoppingCart = angular.module('shoppingCart', []);

ShoppingCart.factory('Item', function() {
  function Item() {
    this.total = function() {
      return (this.qty * this.prize) || 0;
    }
  }

  return Item;
});

ShoppingCart.controller('cartCtrl', function($scope, Item) {
  $scope.cartItems = [new Item(), new Item(), new Item(), new Item()];

  $scope.$watch('cartItems', function() {
    var cartTotal = 0;

    $scope.cartItems.forEach(function(item) {
      cartTotal += item.total();
    });

    $scope.cartTotal = cartTotal;
  }, true);
});

И HTML немного обновляется. Вы ссылаетесь на имя модуля в ng-app, избавляетесь от субконтроллера и ссылаетесь на item.total() непосредственно в представлении.

<div ng-app="shoppingCart" ng:controller="cartCtrl">
  <table>
    <tr><th>qty</th><th>prize</th><th>total</th></tr>
    <tr ng:repeat="item in cartItems">
      <td>
        <input ng:model="item.qty"/>
      </td>
      <td>
        <input ng:model="item.prize" />
      </td>
      <td>
        {{item.total()}}
      </td>
    </tr>
  </table>
  total: {{cartTotal}}
</div>

Вот рабочая кодовая ручка.

person Brian Genisio    schedule 24.11.2013
comment
Спасибо, что нашли время ответить. Но, возможно, я недостаточно ясно изложил свой вопрос: я ищу решение, которое содержит расчет количества * приза только один раз. Как я уже сказал, мой реальный расчет более сложный, и я не хочу писать функцию расчета несколько раз. - person Thomas Koch; 24.11.2013
comment
Попался. Я не уловил этого. Существует несколько подходов, но я предпочитаю подход создания класса модели с общей функцией и внедрения его через Angular factory. Я обновил свой пример, чтобы показать, как это делается. - person Brian Genisio; 25.11.2013

Это подход, использующий директиву ng-init для расширения модели и выполнения вычислений.

http://www.ozkary.com/2015/06/angularjs-calculate-totals-using.html

person ozkary    schedule 20.06.2015