Angular ngRepeat 多个 select 字段而不显示已通过 ng-options selected 的数据
Angular ngRepeat multiple select fields without displaying already selected data through ng-options
所以问题的概述;我正在从 api 中检索数据并为其创建一个 CRUD 页面。数据有一组标签,用户可以 select.
下面是代表我的问题的代码示例。用户 selected 的标签由 user.labels
关系表示,可以 selected 的总可用标签由 user.parent.grandparent.labels
.
表示
我可以同步 selection。我似乎无法弄清楚的是如何从任何其他后续 select 字段的选项列表中删除已经 selected 的选项。
angular.module('app', [])
.controller('select', ['$scope', '$filter', '$location',
function($scope, $filter, $location) {
$scope.user = {
"parent": {
"grandparent": {
"labels": [{
"id": 28,
"name": "Label 1",
}, {
"id": 17,
"name": "Label 2",
}, {
"id": 39,
"name": "Label 3",
}, {
"id": 77,
"name": "Label 4"
}, {
"id": 100,
"name": "Label 5"
}]
}
},
"labels": [{
"id": 28,
"name": "Label 1",
"meta": {
"score": 3
}
}, {
"id": 17,
"name": "Label 2",
"meta": {
"score": 5
}
}]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="select">
<div ng-repeat="label in user.labels track by $index">
<div class="form-field">
<span>Label</span>
<select ng-model="user.labels[$index]" ng-options="department.name for department
in user.parent.grandparent.labels track by department.id">
</select>
</div>
<div>
<span>Score</span>
<select ng-model="label.meta.score">
<option value="1">1 (lowest)</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5 (highest)</option>
</select>
</div>
</div>
<button ng-click="user.labels.push({})">Add Label</button>
</div>
您可以在 ng-repeat 中使用过滤器函数来实现这一点,这里有一个示例 Codepen 向您展示了如何操作:
http://codepen.io/anon/pen/ZYveOo
您需要在重复定义中传递过滤器:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | filter:removeSelected track by department.id ">
在范围内引用此函数:
$scope.removeSelected = function(val){
return !_.find($scope.user.labels, function(label) {
return label.id === val.id;
});
};
尽管如此,我认为您遗漏了一个用例,即您希望能够将当前选定的标签包含在选项中,但通过删除所有选定的选项,您将删除该功能。
更新:
那么好吧,经过一番思考后,我想出了以下可以优化但似乎确实按预期工作的过滤器:
.filter('duplicatesFilter', function() {
return function(items, index, selected) {
var res = [selected[index]];
_.forEach(items, function(item){
if(!_.find(selected, function(label) {
return label.id === item.id;
})){
res.push(item);
}
});
return res;
};
})
像这样使用它:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | duplicatesFilter:$index:user.labels track by department.id "></select>
这是我遇到过几次并且每次都解决它的问题。如果我能找到更好地解决问题的自定义过滤器,我稍后会看一下,如果找不到,我会整理这段代码并发布一个;然而,这应该适合您的用例。
工作码笔:
所以问题的概述;我正在从 api 中检索数据并为其创建一个 CRUD 页面。数据有一组标签,用户可以 select.
下面是代表我的问题的代码示例。用户 selected 的标签由 user.labels
关系表示,可以 selected 的总可用标签由 user.parent.grandparent.labels
.
我可以同步 selection。我似乎无法弄清楚的是如何从任何其他后续 select 字段的选项列表中删除已经 selected 的选项。
angular.module('app', [])
.controller('select', ['$scope', '$filter', '$location',
function($scope, $filter, $location) {
$scope.user = {
"parent": {
"grandparent": {
"labels": [{
"id": 28,
"name": "Label 1",
}, {
"id": 17,
"name": "Label 2",
}, {
"id": 39,
"name": "Label 3",
}, {
"id": 77,
"name": "Label 4"
}, {
"id": 100,
"name": "Label 5"
}]
}
},
"labels": [{
"id": 28,
"name": "Label 1",
"meta": {
"score": 3
}
}, {
"id": 17,
"name": "Label 2",
"meta": {
"score": 5
}
}]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="select">
<div ng-repeat="label in user.labels track by $index">
<div class="form-field">
<span>Label</span>
<select ng-model="user.labels[$index]" ng-options="department.name for department
in user.parent.grandparent.labels track by department.id">
</select>
</div>
<div>
<span>Score</span>
<select ng-model="label.meta.score">
<option value="1">1 (lowest)</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5 (highest)</option>
</select>
</div>
</div>
<button ng-click="user.labels.push({})">Add Label</button>
</div>
您可以在 ng-repeat 中使用过滤器函数来实现这一点,这里有一个示例 Codepen 向您展示了如何操作:
http://codepen.io/anon/pen/ZYveOo
您需要在重复定义中传递过滤器:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | filter:removeSelected track by department.id ">
在范围内引用此函数:
$scope.removeSelected = function(val){
return !_.find($scope.user.labels, function(label) {
return label.id === val.id;
});
};
尽管如此,我认为您遗漏了一个用例,即您希望能够将当前选定的标签包含在选项中,但通过删除所有选定的选项,您将删除该功能。
更新:
那么好吧,经过一番思考后,我想出了以下可以优化但似乎确实按预期工作的过滤器:
.filter('duplicatesFilter', function() {
return function(items, index, selected) {
var res = [selected[index]];
_.forEach(items, function(item){
if(!_.find(selected, function(label) {
return label.id === item.id;
})){
res.push(item);
}
});
return res;
};
})
像这样使用它:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | duplicatesFilter:$index:user.labels track by department.id "></select>
这是我遇到过几次并且每次都解决它的问题。如果我能找到更好地解决问题的自定义过滤器,我稍后会看一下,如果找不到,我会整理这段代码并发布一个;然而,这应该适合您的用例。
工作码笔: