Obliczanie sumy powtórzeń pierwiastków w AngularJS ng-repeat
Poniższy skrypt wyświetla koszyk sklepu za pomocą ng-repeat
. Dla każdego elementu w tablicy, wyświetla nazwę elementu, jego ilość i subtotal (product.price * product.quantity
).
Jaki jest najprostszy sposób obliczania całkowitej ceny powtarzających się elementów?
<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>
18 answers
W Szablonie
<td>Total: {{ getTotal() }}</td>
In Controller
$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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-29 12:53:46
Działa to również zarówno na liście filtrów, jak i na liście normalnej. Pierwszą rzeczą, aby utworzyć nowy filtr dla sumy wszystkich wartości z listy, a także podane rozwiązanie dla sumy całkowitej ilości. In details code check it fiddler link.
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}
];
});
Sprawdź to Fiddle Link
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 09:33:05
Zdając sobie sprawę z tego odpowiedział dawno temu, ale chciał opublikować inne podejście nie przedstawione...
Użyj ng-init
, aby przeliczyć sumę. W ten sposób nie musisz iteracji w HTML i iteracji w kontrolerze. W tym scenariuszu myślę, że jest to czystsze/prostsze rozwiązanie. (Jeśli logika liczenia była bardziej złożona, zdecydowanie zalecałbym przeniesienie logiki do kontrolera lub usługi, jeśli jest to właściwe.)
<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>
Oczywiście, w Twoim kontrolerze, po prostu define / initialize your Total
field:
// random controller snippet
function yourController($scope..., blah) {
var vm = this;
vm.Total = 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-15 18:31:12
Możesz obliczyć sumę wewnątrz ng-repeat
Wykonaj:
<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>
Sprawdź wynik tutaj: http://plnkr.co/edit/Gb8XiCf2RWiozFI3xWzp?p=preview
W przypadku, gdy wynik automatycznej aktualizacji: http://plnkr.co/edit/QSxYbgjDjkuSH2s5JBPf?p=preview (Thanks-VicJordan)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 13:27:40
This is my solution
Słodki i prosty filtr niestandardowy:
(ale związane tylko z prostą sumą wartości, nie sumą produktu, wymyśliłem filtr sumProduct
i dodałem go jako edit do tego postu).
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 Fiddle
EDIT: sumProduct
Jest to filtr sumProduct
, przyjmuje dowolną liczbę argumentów. Jako argument przyjmuje nazwę właściwości z danych wejściowych i może obsługiwać zagnieżdżoną właściwość (zagnieżdżanie oznaczone kropką: property.nested
);
- przekazanie argumentu zerowego zwraca długość danych wejściowych.
- przekazanie tylko jednego argumentu zwraca prostą sumę wartości tych właściwości.
- przekazanie większej ilości argumentów Zwraca sumę produktów wartości przekazanych właściwości (suma skalarna właściwości).
Oto js Fiddle i Kod
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 Fiddle
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-19 14:46:56
Proste Rozwiązanie
Oto proste rozwiązanie. Nie jest wymagana dodatkowa pętla for.część 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>
Script Part
$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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 06:04:09
Inny sposób rozwiązania tego problemu, rozciągający się od odpowiedzi Vaclava do rozwiązania tego konkretnego obliczenia - tj. obliczenia dla każdego wiersza.
.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;
}
};
})
Aby to zrobić z obliczeniami, po prostu dodaj funkcję obliczania do swojego zakresu, np.
$scope.calcItemTotal = function(v) { return v.price*v.quantity; };
Użyłbyś {{ datas|total:calcItemTotal|currency }}
w swoim kodzie HTML. Ma to tę zaletę, że nie jest wywoływany dla każdego digest, ponieważ używa filtrów i może być stosowany do prostych lub złożonych liczb całkowitych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:17
Jest to prosty sposób, aby to zrobić z ng-repeat I ng-init, aby połączyć wszystkie wartości i rozszerzyć model o element.całkowita własność.
<table>
<tr ng-repeat="item in items" ng-init="setTotals(item)">
<td>{{item.name}}</td>
<td>{{item.quantity}}</td>
<td>{{item.unitCost | number:2}}</td>
<td>{{item.total | number:2}}</td>
</tr>
<tr class="bg-warning">
<td>Totals</td>
<td>{{invoiceCount}}</td>
<td></td>
<td>{{invoiceTotal | number:2}}</td>
</tr>
</table>
Dyrektywa ngInit wywołuje funkcję set total dla każdego elementu. Funkcja setTotals w kontrolerze oblicza sumę każdego elementu. Używa również zmiennych zakresu invoiceCount i invoiceTotal do agregowania (sumowania) ilości i sumy dla wszystkich pozycji.
$scope.setTotals = function(item){
if (item){
item.total = item.quantity * item.unitCost;
$scope.invoiceCount += item.quantity;
$scope.invoiceTotal += item.total;
}
}
Aby uzyskać więcej informacji i demo spójrz na to link:
Http://www.ozkary.com/2015/06/angularjs-calculate-totals-using.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 13:16:25
Preferuję eleganckie rozwiązania]}
W Szablonie
<td>Total: {{ totalSum }}</td>
In Controller
$scope.totalSum = Object.keys(cart.products).map(function(k){
return +cart.products[k].price;
}).reduce(function(a,b){ return a + b },0);
Jeśli używasz ES2015 (aka ES6)
$scope.totalSum = Object.keys(cart.products).map(function(k){
return +cart.products[k].price;
}).reduce((a,b) => a + b);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-06 08:51:07
Możesz spróbować skorzystać z usług angular js, to działa dla mnie..podanie poniższego fragmentu kodu
Kod kontrolera:
$scope.total = 0;
var aCart = new CartService();
$scope.addItemToCart = function (product) {
aCart.addCartTotal(product.Price);
};
$scope.showCart = function () {
$scope.total = aCart.getCartTotal();
};
Kod Usługi:
app.service("CartService", function () {
Total = [];
Total.length = 0;
return function () {
this.addCartTotal = function (inTotal) {
Total.push( inTotal);
}
this.getCartTotal = function () {
var sum = 0;
for (var i = 0; i < Total.length; i++) {
sum += parseInt(Total[i], 10);
}
return sum;
}
};
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 00:25:15
Rozszerzyłem nieco odpowiedź Radżashilpy. Możesz użyć składni jak:
{{object | sumOfTwoValues:'quantity':'products.productWeight'}}
Aby uzyskać dostęp do obiektu potomnego. Oto kod dla filtra:
.filter('sumOfTwoValues', function () {
return function (data, key1, key2) {
if (typeof (data) === 'undefined' || typeof (key1) === 'undefined' || typeof (key2) === 'undefined') {
return 0;
}
var keyObjects1 = key1.split('.');
var keyObjects2 = key2.split('.');
var sum = 0;
for (i = 0; i < data.length; i++) {
var value1 = data[i];
var value2 = data[i];
for (j = 0; j < keyObjects1.length; j++) {
value1 = value1[keyObjects1[j]];
}
for (k = 0; k < keyObjects2.length; k++) {
value2 = value2[keyObjects2[k]];
}
sum = sum + (value1 * value2);
}
return sum;
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-20 18:06:53
Biorąc odpowiedź Vaclava i czyniąc ją bardziej kanciastą:
angular.module('myApp').filter('total', ['$parse', function ($parse) {
return function (input, property) {
var i = input instanceof Array ? input.length : 0,
p = $parse(property);
if (typeof property === 'undefined' || i === 0) {
return i;
} else if (isNaN(p(input[0]))) {
throw 'filter total can count only numeric values';
} else {
var total = 0;
while (i--)
total += p(input[i]);
return total;
}
};
}]);
Daje to możliwość dostępu nawet do danych zagnieżdżonych i tablicowych:
{{data | total:'values[0].value'}}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-05 14:42:28
W html
<b class="text-primary">Total Amount: ${{ data.allTicketsTotalPrice() }}</b>
W javascript
app.controller('myController', function ($http) {
var vm = this;
vm.allTicketsTotalPrice = function () {
var totalPrice = 0;
angular.forEach(vm.ticketTotalPrice, function (value, key) {
totalPrice += parseFloat(value);
});
return totalPrice.toFixed(2);
};
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-31 11:17:37
Odpowiedź Huy Nguyena już prawie jest. Aby to działało, dodaj:
ng-repeat="_ in [ products ]"
...do linii z ng-init. Lista zawsze ma jeden element, więc Angular powtórzy blok dokładnie raz.
Demo Zybneka za pomocą filtrowania może działać poprzez dodanie:
ng-repeat="_ in [ [ products, search ] ]"
Zobacz http://plnkr.co/edit/dLSntiy8EyahZ0upDpgy?p=preview .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-21 04:14:58
Oto moje rozwiązanie tego problemu:
<td>Total: {{ calculateTotal() }}</td>
Skrypt
$scope.calculateVAT = function () {
$scope.cart.products.reduce((accumulator, currentValue) => accumulator + (currentValue.price * currentValue.quantity), 0);
};
Reduce wykona dla każdego produktu w tablicy produktów. Accumulator to całkowita zgromadzona kwota, currentValue jest bieżącym elementem tablicy, a 0 w ostatnim jest wartością początkową
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 07:25:36
Można użyć niestandardowego filtra kątowego, który pobiera tablicę obiektów dataset i klucz w każdym obiekcie do sumy. Filtr może wtedy zwrócić sumę:
.filter('sumColumn', function(){
return function(dataSet, columnToSum){
let sum = 0;
for(let i = 0; i < dataSet.length; i++){
sum += parseFloat(dataSet[i][columnToSum]) || 0;
}
return sum;
};
})
Następnie w tabeli sumować kolumnę można użyć:
<th>{{ dataSet | sumColumn: 'keyInObjectToSum' }}</th>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 11:55:27
**Angular 6: Grand Total**
**<h2 align="center">Usage Details Of {{profile$.firstName}}</h2>
<table align ="center">
<tr>
<th>Call Usage</th>
<th>Data Usage</th>
<th>SMS Usage</th>
<th>Total Bill</th>
</tr>
<tr>
<tr *ngFor="let user of bills$">
<td>{{ user.callUsage}}</td>
<td>{{ user.dataUsage }}</td>
<td>{{ user.smsUsage }}</td>
<td>{{user.callUsage *2 + user.dataUsage *1 + user.smsUsage *1}}</td>
</tr>
<tr>
<th> </th>
<th>Grand Total</th>
<th></th>
<td>{{total( bills$)}}</td>
</tr>
</table>**
**Controller:**
total(bills) {
var total = 0;
bills.forEach(element => {
total = total + (element.callUsage * 2 + element.dataUsage * 1 + element.smsUsage * 1);
});
return total;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 06:15:15
Po przeczytaniu wszystkich odpowiedzi tutaj - jak podsumować zgrupowane informacje, postanowiłem pominąć to wszystko i właśnie załadowałem jedną z bibliotek SQL javascript. Używam alasql, tak to trwa kilka sekund dłużej na czas ładowania, ale oszczędza niezliczoną ilość czasu w kodowaniu i debugowaniu, teraz do grupy i sum () po prostu używam,
$scope.bySchool = alasql('SELECT School, SUM(Cost) AS Cost from ? GROUP BY School',[restResults]);
Wiem, że brzmi to trochę jak rant na angular / js, ale naprawdę SQL rozwiązał to 30 + lat temu i nie powinniśmy musieli ponownie wymyślać go w przeglądarce.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-17 14:14:59