我正在学习AngularJs并且我已经使用ng-repeat
创建了一个动态列表,但现在我找不到下一步的解决方案......
我有以下代码:
HTML:
<div ng-app="app">
<div class="list" ng-controller="ListController">
<div class="row" ng-repeat="prod in prodList">
<div class="prod-name cell">
<input type="checkbox" id="prod-{{ prod.id }}" data-ng-model="orders.prods.prod[prod.id]" value="{{ prod.id }}" data-cb="" /><label for="prod-{{ prod.id }}">{{ prod.name }}</label>
</div>
<div class="prod-size cell">
<label for="prodColor-@{{ prod.id }}">
<select id="prodColor-{{ prod.id }}" data-ng-model="orders.prods.color[prod.id]" data-ng-options="color.id as color.name for color in prod.colors">
<option value="">Select one</option>
</select>
</label>
</div>
<div class="prod-price cell">
{{ prod.price }}
</div>
</div>
<div class="sum">
{{ sum }}
</div>
</div>
</div>
JS:
var app = angular.module("app", [], function () {
});
app.controller('ListController', function ($scope) {
init();
function init () {
$scope.prodList = [{"id":"1","name":"window","colors":[{"id":"9","name":"white"},{"id":"11","name":"black"}],"price":"100"},{"id":"2","name":"door","colors":[{"id":"22","name":"blue"},{"id":"23","name":"red"}],"price":"356"},{"id":"3","name":"table","colors":[{"id":"37","name":"white"},{"id":"51","name":"black"}],"price":"505"}];
$scope.orders = {};
$scope.orders.prods = {};
$scope.orders.prods.prod = {};
$scope.orders.prods.color = {};
$scope.sum = 0;
}
});
工作演示:
问题
如何在$scope.sum
中计算所选产品价格的摘要?
编辑:
因此,如果从列表中选择“窗口”和“表格”,则总和应包含606.但如果取消选择“表格”,则总和应为100。
提前谢谢!
答案 0 :(得分:2)
您可以$watch
超过$scope.orders.prod
并重新计算总和或(如果效果不是主要问题且对象列表不是很大)您可以使用sum()
在视图中起作用并引用它:
Total: {{sum()}}
$scope.sum = function () {
return $scope.prodList.filter(function (prod) {
return $scope.orders.prods.prod[prod.id];
}).reduce(function (subtotal, selectedProd) {
return subtotal + parseInt(selectedProd.price);
}, 0);
};
/* If the above looks complicated, it is the equivalent of: */
$scope.sum = function () {
var sum = 0;
for (var i = 0; i < $scope.prodList.length, i++) {
var prod = $scope.prodList[i];
if ($scope.orders.prods.prod[prod.id]) {
sum += parseInt(prod.price);
}
}
return sum;
}
如果你决定走下观察路径,这就是代码的样子:
Total: {{watchedSum}}
$scope.sum = ...; // same as above
$scope.$watchCollection('orders.prods.prod', function (newValue, oldValue) {
if (newValue !== undefined) {
$scope.watchedSum = $scope.sum();
}
});
<子>
的更新:强>
“偷”Quad的$watchCollection
因为这比$watch(..., true)
更“便宜”
只要$scope.order.prods.prod
仅包含边缘值(即没有对象),$watchCollection
就足以检测到更改。
子>
另请参阅此 short demo ,说明这两种方法。
答案 1 :(得分:1)
这是一个更新的小提琴。 http://jsfiddle.net/HRQ9u/
我所做的是在订单上添加$scope.$watch
:
$scope.$watch('orders', function (newValue, oldValue) {
var findProdById = function (products, id) {
for (var i = 0; i < products.length; i++) {
if (parseInt(products[i].id, 10) === parseInt(id, 10)) {
return products[i];
}
}
return null;
};
var orders = newValue;
var usedProducts = newValue.prods.prod;
var sum = 0;
for ( var prop in usedProducts ){
var prodList = $scope.prodList;
var id = prop;
if ( usedProducts[id] ){
var product = findProdById(prodList, id);
if ( product !== null ){
sum += parseInt(product.price, 10);
}
}
}
$scope.sum = sum;
}, true);
编辑:
话虽如此,你可以大大简化你的模型。我的意思是很多。
另外,我只使用常规js而不是lodash或下划线。
答案 2 :(得分:1)
更新了您的小提琴FIDDLE
你可以$ scope。$ watchCollection你的范围来计算新的总和。我将你的prodList价格改为数字而不是字符串,并使用underscore.js更容易在你的对象/数组中循环。
$scope.$watchCollection("orders.prods.prod",function(){
var sum = 0;
for(var i = 0;i<$scope.prodList.length;i++){
if($scope.orders.prods.prod[$scope.prodList[i].id]){
sum += $scope.prodList[i].price;
}
}
$scope.sum = sum;
});
编辑:使用常规js回答更改
答案 3 :(得分:1)
使用复选框注册 ng-click 并传递 $ event &amp; prod.id 引用了一个自定义函数,该函数将在复选框点击事件中调用。
<input type="checkbox" id="prod-{{ prod.id }}" data-ng-model="orders.prods.prod[prod.id]" value="{{ prod.price }}" ng-click="calcSum($event, prod.id)" data-cb="" />
在控制器中将自定义功能定义为:
$scope.calcSum = function($event, id) {
var checkbox = $event.target;
if (checkbox.checked ) {
$scope.sum += parseInt(checkbox.value);
} else {
$scope.sum -= parseInt(checkbox.value);
}
}
更改复选框值属性以存储 {{prod.price}} 而不是{{prod.id}},这更有意义。
答案 4 :(得分:1)
从我的POV中,使用来自ngChange
本身的 input[checkbox]
更合适。像:
ng-change="addMe(prod.price);"
我们需要一种方法来区分已检查和未检查,并且为了减少您的应用程序,我们将通过这种方式使用对象的存在:
ng-change="addMe(orders.prods.prod[prod.id],prod.price);"
ng-true-value="{{ prod.id }}"
ng-false-value=""
完整的 HTML 将如下所示:
<input type="checkbox" id="prod-{{ prod.id }}" data-ng-model="orders.prods.prod[prod.id]" ng-change="addMe(orders.prods.prod[prod.id],prod.price);" ng-true-value="{{ prod.id }}" ng-false-value="" />
通过控制器,您只需在必要时添加或减少:
$scope.addMe=function(checked,val){
val = 1*val
if (!checked){ $scope.sum = $scope.sum-val;}
else { $scope.sum = $scope.sum +val; }
}
以下是Online Demo