23

I have few filters in view

  <tr ng-repeat="x in list | filter:search| offset:currentPage*pageSize| limitTo:pageSize ">

In my project to achieve good result, i have to make this filtering in controller not in view

i know the basic syntax $filter('filter')('x','x') but i don't know how to make chain of filters in controller, so everything will work as in my example from template.

I found some solution, now just with one filter, but should work with many ;)

       $scope.data = data; //my geojson from factory//

       $scope.geojson = {}; //i have to make empty object to extend it scope later with data, it is solution i found for leaflet //

       $scope.geojson.data = [];

       $scope.FilteredGeojson = function() {

       var result = $scope.data;

       if ($scope.data) {
          result = $filter('limitTo')(result,10);
          $scope.geojson.data = result;
          console.log('success');
       }
           return result;

       };

and i use this function in ng-repeat works fine, but i have to check it with few filters.

3 Answers 3

25

You can just re-filter what you get returned from your first filter. So on and so forth.

var filtered;
filtered = $filter('filter')($scope.list, {name: $scope.filterParams.nameSearch});
filtered = $filter('orderBy')(filtered, $scope.filterParams.order);

Below plunkr demonstrates the above.

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

Sign up to request clarification or add additional context in comments.

3 Comments

Nice thanks for help, i will try your solution, but i found some idea as well, just updated post.
Doing it in your way working better then my ;), but if you could just look on my example which i added latter to the question, my way with conditionals works fine with one filter, but i don't know how to add few filters in conditional way, is still possible to do it somehow similar to your way? it is just my curiosity ;)
not a good solution from performance perspective, as it iterates your list multiple times, this can be a problem if you have large data set.
10

In addition to explicitly applying filters to the result of the previous one you could also build an object that will chain multiple filters together.

Controller

angular.module('Demo', []);

angular.module('Demo')
    .controller('DemoCtrl', function($scope, $filter) {

        $scope.order = 'calories';
        $scope.filteredFruits = $scope.fruits = [{ name: 'Apple', calories: 80 }, { name: 'Grapes', calories: 100 }, { name: 'Lemon', calories: 25 }, { name: 'Lime', calories: 20 }, { name: 'Peach', calories: 85 }, { name: 'Orange',    calories: 75 }, { name: 'Strawberry', calories: 65 }];

        $scope.filterFruits = function(){
            var chain = new filterChain($scope.fruits);
            $scope.filteredFruits = chain
                .applyFilter('filter', [{ name: $scope.filter }])
                .applyFilter('orderBy', [ $scope.order ])
                .value;
        };

        function filterChain(value) {
            this.value = value;
        }

        filterChain.prototype.applyFilter = function(filterName, args) {
            args.unshift(this.value);
            this.value = $filter(filterName).apply(undefined, args)
            return this;
        };
    });

View

<!doctype html>
<html ng-app="Demo">
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
    <script src="script.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

<div ng-controller="DemoCtrl">
  <input type="text" ng-model="filter" ng-change="filterFruits()" placeholder="Filter Fruits" />
  <select ng-model="order">
    <option value="name">name</option>
    <option value="calories">calories</option>
  </select>
  <div ng-repeat="fruit in filteredFruits">
    <strong>Name:</strong> {{fruit.name}}
    <strong>Calories:</strong> {{fruit.calories}}
  </div>
</div>
  </body>
</html>

Comments

4

This is a typical case for FP libraries like lodash or Ramda. Make sure your common data is applied as last arg to each filter. (in this case columns)

$scope.columnDefs = _.compose(
    $filter('filter3'),
    $filter('filter2'),
    $filter('filter1')
)($scope.columns)

or with extra args

$scope.columnDefs = _.compose(
    $filter('filter3').bind(null, optionalArg1, optionalArg2),
    $filter('filter2').bind(null, optionalArg1),
    $filter('filter1')
)($scope.columns)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.