3
votes

I have a form with some input types like text, radio etc. When I submit the form, it lists the entered details below the form(used template and directive for this). I want to do filter in age , ie, the number input type, such that when I give an age range, it should filter profiles with corresponding age range. Here is the plunker :

http://plnkr.co/edit/h8p8rtZuAhCoKClUjgE9?p=preview

    <table border="1" style="width:200px">
   <tr>
       <td> <div>Name : {{  formElement.name }} </div><br> </td> 
   </tr>
   <tr>
       <td> <div>Age : {{ formElement.age }}</div><br> </td>
   </tr>
4
You need to use a filter on ngRepeat. So you need find a way to share the filterModel object between your directives (either using a parent scope or a service). Note though, that it is highly unusual to have the filtering logic separated from the display logic that the filter applies to. It would be a better idea to place the filtering-related stuff in the fasterDisplay directive. - gkalpak

4 Answers

10
votes

You could write a custom filter function that filter by range on a particular field:

$scope.byRange = function (fieldName, minValue, maxValue) {
  if (minValue === undefined) minValue = Number.MIN_VALUE;
  if (maxValue === undefined) maxValue = Number.MAX_VALUE;

  return function predicateFunc(item) {
    return minValue <= item[fieldName] && item[fieldName] <= maxValue;
  };
};

and use it in ng-repeat expression:

<div ng-repeat="formElement in formElements | filter:byRange('age', filterModelMin.age, filterModelMax.age)">

Note that the filterModelMin.age and filterModelMax.age can be used directly in fasterDisplay directive because both fasterForm and fasterDisplay do not have their own scope.

Example plunker: http://plnkr.co/edit/dFbBCKxSxm9RI9dwSeYR?p=preview

2
votes

You can do this using a custom filter select function. In your repeat you can do:

<div  ng-repeat = "formElement in formElements | filter:filterAge">

And the following function in your controller:

$scope.filterAge = function(val) {
  return (val.age > MIN_AGE && val.age < MAX_AGE);
};

However, in your case you have the required values (MIN_AGE and MAX_AGE) in a different directive and in a different scope. You could share this values to the correct directive by either using a service or storing the values in the parent scope and passing the reference into your directives.

2
votes

To expand on runTarm's answer. This will allow you to use nested values with the dot operator:

$scope.byRange = function (fieldName, minValue, maxValue) {
  if (minValue === undefined) minValue = Number.MIN_VALUE;
  if (maxValue === undefined) maxValue = Number.MAX_VALUE;

  return function predicateFunc(item) {
    var keys = fieldName.split('.');
    var val = item;
    for (var i = 0; i < keys.length; i++) {
      val = val[keys[i]];
    }

    return minValue <= val && val <= maxValue;
  };
};

used in your ng-repeat expression like so:

<div ng-repeat="formElement in formElements | filter:byRange('person.age', filterModelMin.age, filterModelMax.age)">
0
votes

This is my solution, this solution works better because after deleting the min and maxlikes inputs all the collection will be returned.

$scope.byRange = function (fieldName, minLikes, maxLikes) {
                    if (minLikes === undefined || maxLikes === undefined || maxLikes === null || minLikes === null) {
                        return function predicateFunctionTwo(item) {
                            return item[fieldName];
                        }
                    } else {
                        return function predicateFunc(item) {
                        return minLikes <= item[fieldName] && item[fieldName] <= maxLikes;
                      };
                  }
                }
<div class="content" ng-repeat="data in addingPlaceService | filter:byRange('likes', minLikes, maxLikes) track by $index">