我正在动态构建一组复选框。单击任何选中的复选框应取消选中第一个(索引方式)复选框。单击任何未选中的复选框应检查最后一个未选中的复选框。
我正在使用ng-repeat构建复选框,如下所示:
<input
type="checkbox"
ng-checked="values[$index]"
ng-repeat="n in values track by $index"
ng-click="click($event,$index)" />
我的控制器看起来像这样:
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
event.preventDefault();
if ($scope.values[n] === true) {
$scope.values[$scope.values.indexOf(true)] = false;
} else {
$scope.values[$scope.values.lastIndexOf(false)] = true;
}
}
以下是http://codepen.io/anon/pen/rVLewJ
的代码我遇到的问题是使用preventDefault似乎阻止了ng-checked更新了你点击的框的渲染(其他框正确地重新渲染)。这会导致显示与$ scope.values不同步。
同样,删除preventDefault并不会阻止你点击的框更改其渲染,但是(我相信因为ng-repeat的保守重新渲染)ng-checked不会触发,所以它也会从同步。
我没有使用ng-changed,因为我特意试图阻止复选框如果你点击“错误”的复选框。无论如何,我尝试使用它而不是ng-clicked并且它没有修复任何东西。
我尝试使用ng-model而不是ng-checked,但这似乎阻止了$ scope.values的改变。使用$ scope。$ apply(),没有帮助。我读过的一些内容让我觉得我可能需要使用$watch
,但我正在教自己Angular这个项目,所以我不确定如何应用它。
Nagasimha Iyengar提供了一个工作解决方案here,我已经简化了
<input
type="checkbox"
ng-model="values[$index]"
ng-repeat="n in values track by $index"
ng-change="click($index)" />
控制器:
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (n) {
if ($scope.values[n] === true) {//clicking on unchecked box
$scope.values[n] = false;
$scope.values[$scope.values.lastIndexOf(false)] = true;
} else {//clicking on checked box
$scope.values[n] = true;
$scope.values[$scope.values.indexOf(true)] = false;
}
}
Codepen:http://codepen.io/anon/pen/zGBKxr
此解决方案基于允许click事件发生,然后在继续使用自定义逻辑之前撤消它。这当然是一个简单的解决方案,但感觉有点不合适。这是解决这个问题最正确的方法吗?
另一个小小的更新。我放弃了ngTouch试图让应用程序在移动设备上感觉更快一些。至少在iOS Safari 8中,ngTouch打破了这个解决方案。在桌面上仍然可以正常工作,但重写的ngClick会阻止此解决方案表单工作。如果你切换回原来建议的逻辑它修复iOS,但当然不能在桌面上工作。我觉得这证实了我的怀疑,即解决方案不正确。
答案 0 :(得分:1)
这是 - 逻辑被逆转了。我使用$ apply超时。修改后的代码:http://codepen.io/nagasimhai/pen/VLjjPe
angular
.module("myApp", [])
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
//event.preventDefault();
//console.log("b", n, $scope.values,$scope.values.indexOf(true), $scope.values.lastIndexOf(false));
if ($scope.values[n] === true) {//clicking on unchecked box
$scope.values[n] = false;
$scope.values[$scope.values.lastIndexOf(false)] = true;
//console.log("11");
} else {//clicking on checked box
$scope.values[n] = true;
$scope.values[$scope.values.indexOf(true)] = false;
//console.log('22');
}
//console.log("a",n, $scope.values);
setTimeout(function () {
$scope.$apply(function () {
});
}, 2000);
}
});
答案 1 :(得分:0)
你的回答有点令人困惑,但我相信我走的是正确的道路。问题。您想要使用的是event.stopPropagation()来阻止事件传播。换句话说,您只希望将事件应用于特定元素。如果使用event.preventDefault(),则取消该事件(如果可取消),而不会停止事件的进一步传播。
angular
.module("myApp", [])
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
event.stopPropagation();
if ($scope.values[n] === true) {
$scope.values[$scope.values.indexOf(true)] = false;
$scope.values[n] = false;
} else {
$scope.values[$scope.values.lastIndexOf(false)] = true;
}
}
});
在codepen http://codepen.io/anon/pen/bdepPW
中尝试输出代码