Skip to content Skip to sidebar Skip to footer

Dropdown Filtering In Multiple Rows

I have multiple rows and each contains a dropdown with Labels. Labels = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L') If we select 'A' as a Label in first row, 'B' i

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 $watching 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"