[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>



답변

템플릿에서

<td>Total: {{ getTotal() }}</td>

컨트롤러에서

$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;
}


답변

이것은 또한 필터와 일반 목록 모두에서 작동합니다. 목록의 모든 값의 합계에 대한 새 필터를 만들고 총 수량의 합계에 대한 솔루션을 만드는 첫 번째 작업입니다. 세부 코드에서 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>

Fiddle 링크 확인


답변

오래 전에 대답했지만 제시되지 않은 다른 접근 방식을 게시하고 싶었습니다.

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>

물론 컨트롤러에서 Total필드 를 정의 / 초기화하면 됩니다.

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


답변

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>

결과 확인 : http://plnkr.co/edit/Gb8XiCf2RWiozFI3xWzp?p=preview

자동 업데이트 결과 : http://plnkr.co/edit/QSxYbgjDjkuSH2s5JBPf?p=preview (감사합니다 – VicJordan)


답변

이것은 내 해결책입니다

달콤하고 간단한 맞춤 필터 :

(그러나 합계 제품이 아닌 단순한 값 합계와 관련이 있으므로 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;
            }
        };
    })

JS 바이올린

편집 : sumProduct

이것은 sumProduct필터이며 여러 인수를 허용합니다. 인수로 입력 데이터의 속성 이름을 받아들이고 중첩 된 속성 (점으로 표시된 중첩 :)을 처리 할 수 ​​있습니다 property.nested.

  • 0 인수를 전달하면 입력 데이터의 길이가 반환됩니다.
  • 하나의 인수 만 전달하면 해당 속성 값의 단순 합계가 반환됩니다.
  • 더 많은 인수를 전달하면 전달 된 속성 값의 곱의 합계 (속성의 스칼라 합계)가 반환됩니다.

여기에 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;
            }
        }
    })

JS 바이올린


답변

간단한 솔루션

여기에 간단한 해결책이 있습니다. 추가 for 루프가 필요하지 않습니다.

HTML 부분

         <table ng-init="ResetTotalAmt()">
                <tr>
                    <th>Product</th>
                    <th>Quantity</th>
                    <th>Price</th>
                </tr>

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

                <tr>
                    <td></td>
                    <td>Total :</td>
                    <td>{{cart.TotalAmt}}</td> // Here is the total value of my cart
                </tr>

           </table>

스크립트 부분

 $scope.cart.TotalAmt = 0;
 $scope.CalculateSum= function (product) {
   $scope.cart.TotalAmt += (product.price * product.quantity);
 }
//It is enough to Write code $scope.cart.TotalAmt =0; in the function where the cart.products get allocated value. 
$scope.ResetTotalAmt = function (product) {
   $scope.cart.TotalAmt =0;
 }


답변

이를 해결하는 또 다른 방법은 이 특정 계산을 해결하기위한 Vaclav의 답변 에서 확장됩니다. 즉, 각 행에 대한 계산입니다.

    .filter('total', function () {
        return function (input, property) {
            var i = input instanceof Array ? input.length : 0;
            if (typeof property === 'undefined' || i === 0) {
                return i;
            } else if (typeof property === 'function') {
                var total = 0;
                while (i--)
                    total += property(input[i]);
                return total;
            } else if (isNaN(input[0][property])) {
                throw 'filter total can count only numeric values';
            } else {
                var total = 0;
                while (i--)
                    total += input[i][property];
                return total;
            }
        };
    })

계산으로이를 수행하려면 계산 함수를 범위에 추가하기 만하면됩니다.

$scope.calcItemTotal = function(v) { return v.price*v.quantity; };

{{ datas|total:calcItemTotal|currency }}HTML 코드에서 사용 합니다. 필터를 사용하고 단순하거나 복잡한 합계에 사용할 수 있으므로 모든 다이제스트에 대해 호출되지 않는 이점이 있습니다.

JSFiddle