How to filter values of <select> in angularjs?

107 Views Asked by At

I want to filter the values of a <select>.

I have a table with first column <select> .

For eg: object for the <select> is JSON:

json1 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}, {id: 3, name: 'XYZ'}, {id: 4, name: 'ASD'}, {id: 5, name: 'QWE'}]

json2 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}]

My requirement is: We need to show values from json1 in ng-options but which object should not be there in json2.

For eg: First 2 rows will be filled with json2. So we need to provide options 'XYZ' 'ASD' and 'QWE' in the following rows.

Suppose if name 'XYZ' is selected in the dropdown of the third row. then 4th row <select> should show only 'ASD', and 'QWE'. Similarly what ever object selected in other rows shouldn't be shown in option of other rows dropdown.

I have tried something like this

 <select ng-model="obj"
         ng-options="obj.id as obj.name for obj in json1 | myFilter:json2">
</select>
myApp.filter('myFilter', function(json2) {
return function(json1) {
  var filtered = []; 

  json1.forEach((d) => {
   var exists = false;
      json2.forEach((ad) => {
         if(ad.id == d.id) {
           exists = true;
         }
      });
    if(!exists) filtered.push(d);
  });
  console.log(filetered); 
  return filtered.length > 0 ? filtered : json1;
};
});

In filter console.log() values are filtered correctly as expected. However in ng-options all options from json1 are still available not updated with filtered values.

What's wrong?

2

There are 2 best solutions below

2
nevada_scout On

I think you have the parameters to your filter slightly wrong. The filter function takes a first parameter as the value to be filtered and the other parameters are the ones after myFilter:.

I'm not 100% sure what you want to happen here, but your filter function is called for each value in the dropdown list and should return a replacement for the given value.

However, your code is returning an array of items. This is not how a filter works in AngularJS.

Your filter needs to be updated to check if the item being passed into the filter should be shown or not, and if not, return false.

You can look at the script example from the AngularJS docs to see how they show to do this, or this other Stack Overflow question/answer.

0
Luis Vasquez On

Is this what you are looking for?

For example:

<table>
<thead>
    <tr>
        <th>Unique</th>
        <th>Name</th>
    </tr>
</thead>
<tbody>
    <tr ng-repeat="product in products">
        <td>
            <select ng-model="product.unique" ng-options="obj.id as obj.name for obj in (json1 | myfilter:products:$index)">
                <option value="">No select</option>
            </select>
        </td>
        <td ng-bind="product.name"></td>
    </tr>
</tbody>
</table>

vm.products = [{name: 'Product 1'}, {name: 'Product 2'}, {name: 'Product 3'}, {name: 'Product 4'}, {name: 'Product 5'}];
vm.json1 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}, {id: 3, name: 'XYZ'}, {id: 4, name: 'ASD'}, {id: 5, name: 'QWE'}];

App.filter('myfilter' , [function() {
    return function(json1, products, index) {
        // Filter all products, except the mime
        productsFilter = products.filter(function(product, i) {
                return i !== index;
        });

        // filter those that have not yet been selected
        var json1Filter = json1.filter(function(item) {

            // ask if there is the id in a product
            return !productsFilter.some(function(product) {
                return item.id == product.unique;
            });
        });
        return json1Filter;
    };
}]);

Example Codepen: https://codepen.io/anon/pen/vMJyLz