Как связать фильтры AngularJS в контроллере

У меня есть несколько фильтров в поле зрения

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

В моем проекте для достижения хорошего результата я должен сделать эту фильтрацию в контроллере не в поле зрения

я знаю базовый синтаксис $filter('filter')('x','x') но не знаю как сделать цепочку фильтров в контроллере, поэтому все будет работать как в моем примере из шаблона.

Я нашел какое-то решение, теперь только с одним фильтром, но должно работать со многими ;)

       $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;

       };

и я использую эту функцию в ng-repeat, работает нормально, но мне нужно проверить ее с помощью нескольких фильтров.


person IOR88    schedule 09.01.2015    source источник


Ответы (3)


Вы можете просто повторно отфильтровать то, что вы получили от первого фильтра. Так далее и тому подобное.

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

Ниже plunkr демонстрирует сказанное выше.

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

person Angad    schedule 09.01.2015
comment
Большое спасибо за помощь, я попробую ваше решение, но я также нашел некоторую идею, только что обновил сообщение. - person IOR88; 09.01.2015
comment
Выполнение этого по-вашему работает лучше, чем мой;), но если бы вы могли просто посмотреть на мой пример, который я добавил последним к вопросу, мой способ с условными выражениями отлично работает с одним фильтром, но я не знаю, как добавить несколько фильтров условно, а можно сделать как-то похоже на ваш? это просто мое любопытство ;) - person IOR88; 12.01.2015
comment
не очень хорошее решение с точки зрения производительности, так как он повторяет ваш список несколько раз, это может быть проблемой, если у вас большой набор данных. - person doranT; 29.11.2017

В дополнение к явному применению фильтров к результату предыдущего вы также можете создать объект, который будет объединять несколько фильтров вместе.

Контроллер

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;
        };
    });

Вид

<!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>
person Jonathan Palumbo    schedule 09.01.2015

Это типичный случай для библиотек FP, таких как lodash или Ramda. Убедитесь, что ваши общие данные применяются в качестве последнего аргумента для каждого фильтра. (в данном случае столбцы)

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

или с дополнительными аргументами

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