计算AngularJS ng-repeat中重复元素的总和

kee*_*ach 107 angularjs angularjs-ng-repeat

下面的脚本显示了使用的购物车ng-repeat.对于数组中的每个元素,它显示项目名称,其数量和小计(product.price * product.quantity).

计算重复元素总价的最简单方法是什么?

<table>

    <tr>
        <th>Product</th>
        <th>Quantity</th>
        <th>Price</th>
    </tr>

    <tr ng-repeat="product in cart.products">
        <td>{{product.name}}</td>
        <td>{{product.quantity}}</td>
        <td>{{product.price * product.quantity}} €</td>
    </tr>

    <tr>
        <td></td>
        <td>Total :</td>
        <td></td> <!-- Here is the total value of my cart -->
    </tr>

</table>
Run Code Online (Sandbox Code Playgroud)

Vam*_*msi 145

在模板中

<td>Total: {{ getTotal() }}</td>
Run Code Online (Sandbox Code Playgroud)

在控制器中

$scope.getTotal = function(){
    var total = 0;
    for(var i = 0; i < $scope.cart.products.length; i++){
        var product = $scope.cart.products[i];
        total += (product.price * product.quantity);
    }
    return total;
}
Run Code Online (Sandbox Code Playgroud)

  • 这样做的一个缺点是它会对集合进行两次迭代.这对小型收藏品来说很好,但如果收藏品相当大呢?似乎在ng-repeat中应该有一种方法可以在给定的对象字段上获得运行总和. (24认同)
  • 另外,如果过滤产品列表,则不会更新 (15认同)
  • @Pascamel检查我的答案(http://stackoverflow.com/questions/22731145/calculating-sum-of-repeated-elements-in-angularjs-ng-repeat/25885501#25885501)我认为那个工作正在你所要求的关于过滤器 (2认同)
  • 这个解决方案的主要问题是每个摘要都会重新计算总数,因为它是一个函数调用. (2认同)

Raj*_*amy 57

这也适用于过滤器和普通列表.首先要为列表中的所有值的总和创建一个新过滤器,并给出总量的总和的解决方案.在详细代码中检查它fiddler链接.

angular.module("sampleApp", [])
        .filter('sumOfValue', function () {
        return function (data, key) {        
            if (angular.isUndefined(data) || angular.isUndefined(key))
                return 0;        
            var sum = 0;        
            angular.forEach(data,function(value){
                sum = sum + parseInt(value[key], 10);
            });        
            return sum;
        }
    }).filter('totalSumPriceQty', function () {
        return function (data, key1, key2) {        
            if (angular.isUndefined(data) || angular.isUndefined(key1)  || angular.isUndefined(key2)) 
                return 0;        
            var sum = 0;
            angular.forEach(data,function(value){
                sum = sum + (parseInt(value[key1], 10) * parseInt(value[key2], 10));
            });
            return sum;
        }
    }).controller("sampleController", function ($scope) {
        $scope.items = [
          {"id": 1,"details": "test11","quantity": 2,"price": 100}, 
          {"id": 2,"details": "test12","quantity": 5,"price": 120}, 
          {"id": 3,"details": "test3","quantity": 6,"price": 170}, 
          {"id": 4,"details": "test4","quantity": 8,"price": 70}
        ];
    });


<div ng-app="sampleApp">
  <div ng-controller="sampleController">
    <div class="col-md-12 col-lg-12 col-sm-12 col-xsml-12">
      <label>Search</label>
      <input type="text" class="form-control" ng-model="searchFilter" />
    </div>
    <div class="col-md-12 col-lg-12 col-sm-12 col-xsml-12">
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2">
        <h4>Id</h4>

      </div>
      <div class="col-md-4 col-lg-4 col-sm-4 col-xsml-4">
        <h4>Details</h4>

      </div>
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">
        <h4>Quantity</h4>

      </div>
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">
        <h4>Price</h4>

      </div>
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">
        <h4>Total</h4>

      </div>
      <div ng-repeat="item in resultValue=(items | filter:{'details':searchFilter})">
        <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2">{{item.id}}</div>
        <div class="col-md-4 col-lg-4 col-sm-4 col-xsml-4">{{item.details}}</div>
        <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">{{item.quantity}}</div>
        <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">{{item.price}}</div>
        <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">{{item.quantity * item.price}}</div>
      </div>
      <div colspan='3' class="col-md-8 col-lg-8 col-sm-8 col-xsml-8 text-right">
        <h4>{{resultValue | sumOfValue:'quantity'}}</h4>

      </div>
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">
        <h4>{{resultValue | sumOfValue:'price'}}</h4>

      </div>
      <div class="col-md-2 col-lg-2 col-sm-2 col-xsml-2 text-right">
        <h4>{{resultValue | totalSumPriceQty:'quantity':'price'}}</h4>

      </div>
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

检查这个小提琴链接


tsi*_*orn 41

很久以前意识到这个回答了,但想发布不提出的不同方法......

使用ng-init相符您的总.这样,您不必迭代HTML并在控制器中迭代.在这种情况下,我认为这是一个更简洁/更简单的解决方案.(如果计数逻辑更复杂,我肯定会建议将逻辑移动到控制器或服务中.)

    <tr>
        <th>Product</th>
        <th>Quantity</th>
        <th>Price</th>
    </tr>

    <tr ng-repeat="product in cart.products">
        <td>{{product.name}}</td>
        <td>{{product.quantity}}</td>
        <td ng-init="itemTotal = product.price * product.quantity; controller.Total = controller.Total + itemTotal">{{itemTotal}} €</td>
    </tr>

    <tr>
        <td></td>
        <td>Total :</td>
        <td>{{ controller.Total }}</td> // Here is the total value of my cart
    </tr>
Run Code Online (Sandbox Code Playgroud)

当然,在您的控制器中,只需定义/初始化您的Total字段:

// random controller snippet
function yourController($scope..., blah) {
    var vm = this;
    vm.Total = 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是最有棱角的方式.简单,可读和声明.因此,它代表的逻辑仍然属于它所属的地方. (4认同)

Huy*_*yen 17

您可以计算内部ng-repeat跟随总数:

<tbody ng-init="total = 0">
  <tr ng-repeat="product in products">
    <td>{{ product.name }}</td>
    <td>{{ product.quantity }}</td>
    <td ng-init="$parent.total = $parent.total + (product.price * product.quantity)">${{ product.price * product.quantity }}</td>
  </tr>
  <tr>
    <td>Total</td>
    <td></td>
    <td>${{ total }}</td>
  </tr>
</tbody>
Run Code Online (Sandbox Code Playgroud)

在此处查看结果:http://plnkr.co/edit/Gb8XiCf2RWiozFI3xWzp?p = preview

如果自动更新结果:http://plnkr.co/edit/QSxYbgjDjkuSH2s5JBPf?p = preview(谢谢 - VicJordan)


Vac*_*tny 9

这是我的解决方案

甜美简单的自定义过滤器:

(但只与简单的值之和,而不是和产品相关,我已经组成了sumProduct过滤器并将其作为编辑添加到此帖子中).

angular.module('myApp', [])

    .filter('total', function () {
        return function (input, property) {
            var i = input instanceof Array ? input.length : 0;
// if property is not defined, returns length of array
// if array has zero length or if it is not an array, return zero
            if (typeof property === 'undefined' || i === 0) {
                return i;
// test if property is number so it can be counted
            } else if (isNaN(input[0][property])) {
                throw 'filter total can count only numeric values';
// finaly, do the counting and return total
            } else {
                var total = 0;
                while (i--)
                    total += input[i][property];
                return total;
            }
        };
    })
Run Code Online (Sandbox Code Playgroud)

JS小提琴

编辑:sumProduct

这是sumProduct过滤器,它接受任意数量的参数.作为参数,它接受来自输入数据的属性的名称,并且它可以处理嵌套属性(由dot标记的嵌套property.nested);

  • 传递零参数返回输入数据的长度.
  • 仅传递一个参数会返回该属性的简单值.
  • 传递更多参数会返回传递属性值(属性的标量和)的乘积之和.

这里是JS Fiddle和代码

angular.module('myApp', [])
    .filter('sumProduct', function() {
        return function (input) {
            var i = input instanceof Array ? input.length : 0;
            var a = arguments.length;
            if (a === 1 || i === 0)
                return i;

            var keys = [];
            while (a-- > 1) {
                var key = arguments[a].split('.');
                var property = getNestedPropertyByKey(input[0], key);
                if (isNaN(property))
                    throw 'filter sumProduct can count only numeric values';
                keys.push(key);
            }

            var total = 0;
            while (i--) {
                var product = 1;
                for (var k = 0; k < keys.length; k++)
                    product *= getNestedPropertyByKey(input[i], keys[k]);
                total += product;
            }
            return total;

            function getNestedPropertyByKey(data, key) {
                for (var j = 0; j < key.length; j++)
                    data = data[key[j]];
                return data;
            }
        }
    })
Run Code Online (Sandbox Code Playgroud)

JS小提琴