我正在使用AngularJS v1.2.0-rc.3。
我有一个与模型x有1对多关系的模型y。
最初,我有一个模型y的表单,其中包含xs的多重选择,如下所示:
控制器:
function test($scope) {
$scope.xs = [
{id:1, value:'value 1'},
{id:2, value:'value 2'},
{id:3, value:'value 3'}
];
$scope.y = {xs:[2]};
}
查看:
<div ng-controller="test">
<select multiple ng-model="y.xs" ng-options="x.id as x.value for x in xs">
</select>
</div>
结果是所选项目的数组。
http://plnkr.co/edit/s3tvvHeyE17TVH5KNkPZ
一切都很好,但我需要将其更改为复选框列表,发现我再也无法使用数组了。
我尝试使用转发器的索引,如下所示:
<div ng-repeat="x in xs">
<input type="checkbox" ng-model="y.xs[$index]" ng-true-value="{{x.id}}"/>
{{x.value}}
</div>
但是要预先选择第二项,我需要使用它:
$scope.y = {xs: [null, '2']};
没用。
http://plnkr.co/edit/9UfbKF2gFLnhTOKu3Yep
经过一些搜索,似乎推荐的方法是使用对象哈希,如此
<div ng-repeat="x in xs">
<input type="checkbox" ng-model="y.xs[x.id]"/>
{{x.value}}
</div>
http://plnkr.co/edit/Xek8alEJbwq3g0NAPMcF
但如果取消选择项目,您最终会看到如下内容:
y={
"xs": {
"1": false,
"2": false,
"3": false
}
}
所以我最后添加了一个监视表达式来过滤掉错误值,如下所示:
$scope.$watch('y.xs', function(n) {
for (var k in n)
if (n.hasOwnProperty(k) && !n[k])
delete n[k];
}, true);
http://plnkr.co/edit/S1C1g5fYKzUZb7b0pRtp
它有效,但感觉不尽如人意。
由于这是一个常见的用例,我很想知道其他人是如何解决它的。
更新
根据建议使用自定义指令,我提出了这个解决方案,将选择保持为列表。
指令:
angular.module('checkbox', [])
.directive('checkboxList', function () {
return {
restrict: 'A',
replace: true,
scope: {
selection: '=',
items: '=',
value: '@',
label: '@'
},
template: '<div ng-repeat="item in list">' +
'<label>' +
'<input type="checkbox" value="{{item.value}}" ng-checked="item.checked" ng-click="toggle($index)"/>' +
'{{item.label}}' +
'</label>' +
'</div>',
controller: ['$scope', function ($scope) {
$scope.toggle = function (index) {
var item = $scope.list[index],
i = $scope.selection.indexOf(item.value);
item.checked = !item.checked;
if (!item.checked && i > -1) {
$scope.selection.splice(i, 1);
} else if (item.checked && i < 0) {
$scope.selection.push(item.value);
}
};
$scope.$watch('items', function (value) {
$scope.list = [];
if (angular.isArray(value)) {
angular.forEach(value, function (item) {
$scope.list.push({
value: item[$scope.value],
label: item[$scope.label],
checked: $scope.selection.indexOf(item[$scope.value]) > -1
});
});
}
}, true);
}]
};
});
查看:
<div checkbox-list
selection="a.bs"
items="bs"
value="id"
label="name">
</div>
答案 0 :(得分:2)
我过去必须自己编写一个多选指令,随时可以在http://isteven.github.io/angular-multi-select抓住它。
至于数据绑定方法,我的数据结构实际上与你的数据结构非常相似,但在我的方法中,我添加了一个表示复选框状态的属性。
示例,根据您的输入,我添加了“已选中”:
$scope.xs = [
{ id:1, value:'value 1', checked: false },
{ id:2, value:'value 2', checked: false },
{ id:3, value:'value 3', checked: false }
];
我把它传递给这样的指令:
<div
multi-select
input-model="xs"
button-label="value"
item-label="id value"
tick-property="checked" >
</div>
当勾选/取消选中复选框时,该指令将相应地修改输入模型$ scope.xs.checked。为此,我为每个复选框附加了一个单击处理程序。这个处理程序将调用一个函数,我在其中传递checkbox对象作为函数参数。然后,此函数将同步复选框状态和模型。
要获取所选/勾选的复选框,您只需将$scope.xs
循环到.checked === true
示例:
angular.forEach( $scope.xs, function( value, key ) {
if ( value.checked === true ) {
// Do your stuff here
}
});
请原谅我糟糕的英语,并希望这会有所帮助。欢呼声。
答案 1 :(得分:1)
我采用了指令方法。它给我留下了一个被检查对象的id列表。这是它的小提琴JSFIDDLE。 这就是我的html的样子。
<div ng-app="checkbox" ng-controller="homeCtrl">
<div ng-repeat="item in list">
<input type="checkbox" checkbox-group />
<label>{{item.value}}</label>
</div>{{array}}
<br>{{update()}}
</div>
我的指示
.directive("checkboxGroup", function () {
return {
restrict: "A",
link: function (scope, elem, attrs) {
// Determine initial checked boxes
if (scope.array.indexOf(scope.item.id) !== -1) {
elem[0].checked = true;
}
// Update array on click
elem.bind('click', function () {
var index = scope.array.indexOf(scope.item.id);
// Add if checked
if (elem[0].checked) {
if (index === -1) scope.array.push(scope.item.id);
}
// Remove if unchecked
else {
if (index !== -1) scope.array.splice(index, 1);
}
// Sort and update DOM display
scope.$apply(scope.array.sort(function (a, b) {
return a - b
}));
});
}
}
});
答案 2 :(得分:0)
我需要一个复选框解决方案,该解决方案还会显示不在可能选项列表中的值(如果自用户填写表单后该列表已更改,该怎么办?)。
另外,我并不认为手表功能是必要的。
最后,我需要传入表单,以便在用户切换任何复选框时将其设置为脏。
警告:在我的情况下,我只需要一个字符串数组作为我的模型,这不是海报用于他的模型的内容。
HTML:
<multiple-checkbox
form="form"
selections="model"
options="options">
</multiple-checkbox>
指令:
.directive("multipleCheckbox", function () {
return {
restrict: 'E',
scope: {
form: '=',
selections: '=',
options: '=',
},
template:
'<div>' +
'<div class="checkbox" ng-repeat="item in options">' +
'<label>' +
'<input type="checkbox" value="{{$index}}" ng-checked="selections.indexOf(item) > -1" ng-click="toggle(item)"/>' +
'{{item}}' +
'</label>' +
'</div>' +
'<div class="checkbox" ng-repeat="item in selections" ng-if="options.indexOf(item) === -1">' +
'<label>' +
'<input type="checkbox" value="{{options.length + $index}}" ng-checked="selections.indexOf(item) > -1" ng-click="toggle(item)"/>' +
'<strong>Other: </strong>{{item}}' +
'</label>' +
'</div>' +
'</div>',
controller: ['$scope', function ($scope) {
// Executed when the checkboxes are toggled
$scope.toggle = function (item) {
// set the form to dirty if we checked the boxes
if ($scope.form) $scope.form.$dirty = true;
// get the index of the selection
var index = -1;
if (angular.isArray($scope.selections)) {
index = $scope.selections.indexOf(item);
}
// if it's not already an array, initialize it
else $scope.selections = [];
if (index > -1) {
// remove the item
$scope.selections.splice(index, 1);
// if the array is empty, set it to null
if ($scope.selections.length === 0) {
$scope.selections = null;
}
}
else if (index < 0) {
// add the item
$scope.selections.push(item);
}
};
}],
};
});