AngularJS multichannel custom filter

I am trying to create a custom Angular filter. In my example code, it filters the list of names. Filtering is done using a dropdown picklist with these options:

Contains
Equals
Starts with
Ends with
Does not contain

      

and then there is a text box. The text box will act like a search box based on what's in the dropdown before it. Finally, when you click the filter button, the filtering actually happens. So, if I enter "foo" in the text box, then select "Ends with" from the dropdown, then click "filter", the list should only display entries that end with "foo".

You can see the code here .

Here's my HTML:

<div ng-app="programApp" ng-controller="programController">
  <label>Name: 
    <select ng-model="filterDropdown">
      <option>Contains</option>
      <option>Equals</option>
      <option>Starts with</option>
      <option>Ends with</option>
      <option>Does not contain</option>
    </select>
    <input ng-model="inputField" type="text">
  </label>
  <button ng-click="runFilter()">Filter</button>
  <ul>
    <li ng-repeat="name in names | filter:filterName(name, filterDropdown, filterSearch)">{{name.name}}, <i>{{name.age}}</i></li>
  </ul>
</div>

      

Then, here's the Angular filter (you can find more Angular code in code , but there aren't many):

angular.module('programApp.filters', []).filter('filterName', function(){
    return function(entries, filterDropdown, filterInput) {
        //Each of these if statements should check which dropdown option is selected and return filtered elements accordingly.
        if(filterDropdown == 'Contains'){
            return entries.name.match(filterInput);
        }else if(filterDropdown == 'Equals'){
            return entries.name.match(filterInput);
        }else if(filterDropdown == 'Starts with'){
            if(entries.name.indexOf(filterInput) === 0){
                return entries;
            };
        }else if(filterDropdown == 'Ends with'){
            if(entries.name.indexOf(filterInput, entries.name.length - filterInput.length) !== -1){
                return entries;
            };
        }else if(filterDropdown == 'Does not contain'){
            return entries.name.match(!filterInput);
        };
    };
});

      

And here is my simple function that runs when you click "filter" (which means that when you enter a text box, the filter is not applied until you click the filter button).

$scope.runFilter = function(){
  $scope.filterSearch = $scope.inputField;
};

      

However, when I run it, I get no errors, but the filters don't actually do anything. What's wrong with my custom filter?

Codepen Here .

+3


source to share


1 answer


1) The syntax of your HTML filter is incorrect. You don't put filter

in the beginning because this is an already existing Angular filter called filter

. Just put on the one you made. The arguments are then separated by colons, and the first argument is the entire array, but it is implied and you are not writing it.

ng-repeat="thing in things | filterName:filterDropdown:filterSearch"

      

2) You are trying to access the property of each record, but writing entries.name

. entries

are your array, not each element, so you need to iterate over them. Angular has an excellent angular.forEach(array, function (item, index) {...})

one that is designed for exactly this purpose.



3) Your filter should return an array. Create a new array at the beginning of your filter, iterate over your elements with forEach

, and if the element passes the test, add it to the array and return it.

Codepen

+1


source







All Articles