Dropdown Filtering In Multiple Rows
Solution 1:
You could do it easily using the lodash library to manipulate arrays and collections.
EDIT-1: I added an alternative and modified the plunker accordingly.
EDIT-2: I added an other alternative using a custom filter
DEMO:http://plnkr.co/edit/Sf3el0FyUptWq28XqZnI?p=preview
Let's say that you have a certain number of rows (list) each having a dropdown (select). The dropdown must have all the values that were not selected yet (remaining).
html
<ul><ling-repeat="item in list">
{{item.id}}-{{item.value}}
<selectng-model="item.value"ng-options="letter for letter in remaining"></select></li></ul>
Whenever a item of the list change the dropdown value, the remaining values are updated.
js
$scope.$watch('list', function(newval) {
$scope.remaining = _.difference($scope.letters, _.map(newval, 'value'));
}, true);
The possible list of values:
$scope.letters = [
'A','B','C','D','E','F','G','H','I','J'
]
The list of items:
$scope.list = [
{id:1,value:''},
{id:2,value:''},
{id:3,value:''},
{id:4,value:''},
{id:5,value:''},
{id:6,value:''},
{id:7,value:''},
{id:8,value:''}
];
lodash
We use lodash to easily _.map
the value
property of all the items in the list to an array. And we want the _.difference
between the selected and the possible values.
alternative tracking previous values
If your list of possible values is represented as a string ($scope.letters='ABCDEFGHIJ';
), then you can keep track of the remaining values as a string too ($scope.remaining='BDEGHJ';
). Then, instead of $watch
ing every changes, you can use the ng-change
directive on the dropdowns and add or remove the values with a simple string.replace
. You need to keep track of the previously selected values in order to put them back in the list when they are switched.
html
<ul><ling-repeat="item in list2">
{{item.id}}-{{item.value}}
<selectng-model="item.value"ng-change="select(item)"ng-options="letter for letter in remaining2"></select></li></ul>
js
var last = [];
$scope.select = function(item) {
$scope.remaining2 = $scope.remaining2.replace(item.value,last[item.id]||'');
last[item.id] = item.value;
}
Here I use the item.id
to keep track of the previous value of each items, but you could think of another approach.
alternative using a filter
This has not been tested, but it should work.
There are a lot of other ways to achieve this, for example, using a custom $filter on the list of all possible values (the filter would need access to the currently selected values). It could be a simple wrapper of one of my solutions.
html
<select ng-model="item.value" ng-options="letter for letter in letters | notselected:list:'value'"></select>
This will take as input the $scope.letters
and remove the ones used in $scope.list
. We must tell the filter which property correspond to the selected values in the collection.
js
app.filter('notselected', function() {
returnfunction(input, list, prop) {
return _.difference(input, _.map(list, prop));
}
});
This might be the most elegant solution in my opinion. Lodash is an amazing library and works like a charm with Angular!
Post a Comment for "Dropdown Filtering In Multiple Rows"