我有一个有分数的人的阵列。我会显示带有分数和复选框的人员列表。当用户选中复选框时,我会检查所有已检查的分数: http://jsfiddle.net/edwardtanguay/hwutbgv3/16
然而,由于看起来当Angular执行ng-click
中包含的函数时,总计是一个检查,因此它没有更新ng-model
的值。
如何让Angular更新值FIRST,然后执行该功能?
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="person in persons | orderBy:'score'"><input type="checkbox" ng-model="person.isChecked" ng-click="updateTotals()"/> {{person.name}} = {{person.score}} ({{person.isChecked}})
</li>
</ul>
<div>{{message}}</div>
<div>total score of checked persons: {{total}}</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope, $window) {
$scope.debug = '';
$scope.total = 0;
$scope.persons = [
{score: 1, name: 'Jim', isChecked: true},
{score: 2, name: 'Joe', isChecked: false},
{score: 3, name: 'Angie', isChecked: true}
];
$scope.updateTotals = function() {
$scope.total = 0;
for(var x=0; x < $scope.persons.length; x++) {
var person = $scope.persons[x];
if(person['isChecked']) {
$scope.total += person['score'];
}
}
}
$scope.updateTotals()
}
答案 0 :(得分:2)
这是因为ng-click
在ng-model
更改之前触发,因此您需要使用ng-change
而不是ng-click
。
<li ng-repeat="person in persons | orderBy:'score'">
<input type="checkbox" ng-model="person.isChecked" ng-change="updateTotals(person)"/>
.....
</li>
这是一个DEMO
此外,你可以摆脱控制器updateTotals()
并在视图中管理它,如
在控制器中定义总数
// using a object because we need this inside `ng-repeat` which create a child scope, otherview we need to call it as $parent.total in the view.
$scope.all = {
total: 0
};
in html
<ul>
<li ng-repeat="person in persons | orderBy:'score'" ng-init="person.isChecked ? (all.total = all.total+person.score) : return">
<input type="checkbox" ng-model="person.isChecked" ng-change="person.isChecked ? (all.total = all.total+person.score) : (all.total = all.total-person.score)"/>
{{person.name}} = {{person.score}} ({{person.isChecked}})
</li>
</ul>
使用ng-init
计算初始阶段的总数
...ng-init="person.isChecked ? (all.total = all.total+person.score) : return"...
更改复选框值时添加或减少分数
<input type="checkbox" ng-model="person.isChecked" ng-change="person.isChecked ? (all.total = all.total+person.score) : (all.total = all.total-person.score)"/>
这是DEMO
如果您认为html
有点混乱,请移动条件并将总数更新为controller
在初始阶段和复选框更改阶段调用updateTotal
并传递参数(person&amp; true/false
以指示初始阶段)
<li ng-repeat="person in persons | orderBy:'score'" ng-init="updateTotal(person, true)">
<input type="checkbox" ng-model="person.isChecked" ng-change="updateTotal(person, false)"/>
{{person.name}} = {{person.score}} ({{person.isChecked}})
</li>
控制器中的
$scope.updateTotal = function(person, isInitPhase) {
if (isInitPhase) {
if (person.isChecked) {
$scope.total += person.score;
}
} else {
if (person.isChecked) {
$scope.total += person.score;
} else {
$scope.total -= person.score;
}
}
}
这是DEMO
我选择最后一个,因为我觉得它更清洁。
答案 1 :(得分:0)
不要自己更新视图数据,请使用数据绑定。只需将updateTotals
- 函数重命名为getTotal
,然后将其返回计算总数:
$scope.getTotal = function() {
var total = 0;
for(var x=0; x < $scope.persons.length; x++) {
var person = $scope.persons[x];
if(person['isChecked']) {
total += person['score'];
}
}
return total;
}
并将模板更改为显示getTotal()
:
<div>total score of checked persons: {{getTotal()}}</div>
现在,您可以删除复选框上的ng-click
,让角色为您完成工作。
另外,我建议您查看controllerAs-syntax并开始使用it has a number of different advantages, including readability and removing $scope from your code。