2013-03-16 1 views
20

Так что, если у меня есть массив:Можно ли фильтровать angular.js путем размещения в другом массиве?

$scope.letters = 
[{"id":"a"}, 
{"id":"b"}, 
{"id":"c"}]; 

И еще один массив

$scope.filterBy = ["b","c","d"]; 

И я хочу, чтобы иметь некоторые нг-повтор для фильтрации $ scope.letters лишь на предметы, которые появляются в $ filterBy.

Я хочу, чтобы иметь возможность сделать что-то эффект:

<span ng-repeat="{{letter in letters|filter: letter.id in filterBy }} > {{letter.id}} </span> 

И есть распечатать б,

Я знаю, что это действительно глупый пример, но есть способ фильтровать выражение angular.js на основе содержимого другого объекта массива?

ответ

29

Вы должны попробовать что-то вроде этого:

JS:

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

function Ctrl($scope) { 
    $scope.letters = [ 
    {id: 'a'}, 
    {id: 'b'}, 
    {id: 'c'} 
    ]; 

    $scope.filterBy = ['b', 'c', 'd']; 

    $scope.filteredLetters = function() { 
    return $scope.letters.filter(function (letter) { 
     return $scope.filterBy.indexOf(letter.id) !== -1; 
    }); 
    }; 
} 

Ctrl.$inject = ['$scope']; 

HTML:

<div ng-repeat='letter in filteredLetters(letters)'>{{letter.id}}</div> 

Вы можете попробовать live example.

+6

filterLetters() будет вызван цикл _every_ digest. Поэтому, если у вас есть поле ввода с использованием ng-модели в вашем представлении, это означает каждое нажатие клавиши. Было бы лучше сохранить результаты фильтра в новом свойстве $ scope. Используйте $ watch() es для обновления результатов фильтра, если «буквы» или «filterBy» изменяются. –

+0

Хороший вопрос. Спасибо за совет. – ValeriiVasin

+0

Хотя это будет работать (при условии, что ваше приложение очень простое), я бы не рекомендовал использовать этот подход, как упоминает @MarkRajcok, он называется каждым циклом дайджест, что означает, что производительность ужасна, и я получал ошибки с угловыми, подобными «Ошибка: [$ rootScope: infdig] 10 $ digest() итераций достигнуто. Отмена! " –

35

Update

Вот угловой модуль (на основе @InviS ответа) легко реализовать этот фильтр внутри вашего углового применения: filters-inArrayFilter


Вот угловые фильтры, опирающийся на @InviS ответ:

Фильтр должен быть таким:

.filter('inArray', function($filter){ 
    return function(list, arrayFilter, element){ 
     if(arrayFilter){ 
      return $filter("filter")(list, function(listItem){ 
       return arrayFilter.indexOf(listItem[element]) != -1; 
      }); 
     } 
    }; 
}); 

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

Чтобы использовать этот фильтр вы используете нг-повторение, как:

<div ng-repeat='letter in letters | inArray:filterBy:"id"'>{{letter.id}}</div> 

где inArray является фильтром, filterBy(первый аргумент этого фильтра) это ваш массив, чтобы соответствовать, и «id»(второй аргумент) - это элемент в списке, который вы хотите сопоставить с массивом.

Вы можете попробовать это live example, используя подход угловых фильтров.

+0

Что делать, если мне нужно фильтровать несколько столбцов? Будет ли «цепочка» делать? – dreamer

+0

@dreamer Что вы подразумеваете под несколькими столбцами? – Cyberdelphos

+0

@Cyberdelphos, как бы вы фильтровали, если ключ объекта был числом? использовать $ index? – alphapilgrim

6

Довольно старый, но мне он был нужен, и мне пришлось немного изменить его. Вот мой фильтр "notInArray"

app.filter('notInArray', function($filter){ 
return function(list, arrayFilter, element){ 
    if(arrayFilter){ 
     return $filter("filter")(list, function(listItem){ 
      for (var i = 0; i < arrayFilter.length; i++) { 
       if (arrayFilter[i][element] == listItem[element]) 
        return false; 
      } 
      return true; 
     }); 
    } 
}; 

});

<md-chips ng-model="filter.SelectedValues" md-autocomplete-snap 
      md-require-match="true"> 
     <md-autocomplete 
      md-search-text="searchFilterChip" 
      md-items="val in filter.Values | notInArray:filter.SelectedValues:'Id'" 
      md-item-text="val.Name" 
      md-no-cache="true" 
      md-min-length="0"> 
     <span md-highlight-text="searchFilterChip">{{val.Name}}</span> 
     </md-autocomplete> 
     <md-chip-template> 
     {{$chip.Name}} 
     </md-chip-template> 
    </md-chips> 

Я предположил, что это может быть улучшено, но не нужно в моем случае.

Надеюсь, что кто-то поможет!

+0

thankyou полезно – Magico

Смежные вопросы