Как мне отфильтровать массив с помощью AngularJS и использовать свойство отфильтрованного объекта в качестве атрибута ng-model?

122

Если у меня есть массив объектов, и я хочу привязать модель Angular к свойству одного из элементов на основе фильтра, как мне это сделать? Я могу лучше объяснить на конкретном примере:

HTML:

<!DOCTYPE html>
<html ng-app>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
        <meta charset=utf-8 />
        <title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
        <input ng-model="results.year">
        <input ng-model="results.subjects.title | filter:{grade:'C'}">
    </body>
</html>

контроллер:

function MyCtrl($scope) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
}

JSBin: http://jsbin.com/adisax/1/edit

Я хочу , чтобы фильтровать второй вход к предмету с класса «C», но я не хочу , чтобы связать модель в классе ; Я хочу привязать его к названию предмета с оценкой «С».

Возможно ли это, и если да, то как это делается?

Бернхард Хофманн
источник

Ответы:

127
<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>
JB Nizet
источник
1
Я понимаю, к чему вы клоните, но мне действительно не нужен репитер. Свойство, по которому я буду фильтровать, - это столбец идентификаторов, поэтому он уникален. Но я вижу, что это был бы правильный способ решения общей проблемы.
Bernhard Hofmann
1
это учебник для итальянцев
Сильвио Троя
10
это было очень полезно, и для инверсии (все, кроме C) это сработает:filter:{grade:'!'+'C'}
pulkitsinghal
2
Можете ли вы сделать то же самое с a grade array? В моем случае я строю свой массив оценок из древовидной структуры и хочу отфильтровать результат для тех, кто находится в массиве.
Хуан Карлос Оропеза,
157

Вы можете использовать фильтр «фильтр» в вашем контроллере, чтобы получить все оценки «C». Получение первого элемента массива результатов даст вам название предмета с оценкой «C».

$scope.gradeC = $filter('filter')($scope.results.subjects, {grade: 'C'})[0];

http://jsbin.com/ewitun/1/edit

То же и с простым ES6:

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]
Оливер
источник
Извините, я не следую этому второму фильтру («фильтру»), вы можете объяснить его немного подробнее?
Winnemucca
1
@stevek Это название фильтра. Метод filter () дает вам фильтр. Просто фильтр называется фильтром, потому что он фильтрует массив. С фильтром валюты это выглядело бы так: $ filter ('currency') (amount, symbol, FractionSize) Проверьте документы здесь: docs.angularjs.org/api/ng/filter
Оливер,
61

Вот модифицированный JSBin с рабочим образцом:

http://jsbin.com/sezamuja/1/edit

Вот что я сделал с фильтрами на входе:

<input ng-model="(results.subjects | filter:{grade:'C'})[0].title">
lukeatdesignworks
источник
1
Это реальная сделка. Это сила. Это способ. Я пошел с этим и теперь счастлив.
user1576978
13

обратите внимание, если вы используете $ filter следующим образом:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});

и у вас случайно была другая оценка, о, я не знаю, CC, AC, C + или CCC, она их привлекает. вам нужно добавить требование для точного соответствия:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'}, true);

Это действительно убило меня, когда я вытащил некоторые детали комиссии вроде этого:

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}))[0];

вызвали только за ошибку, потому что она вытаскивала идентификатор комиссии 56, а не 6.

Добавление истинных сил точного совпадения.

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}, true))[0];

Тем не менее, я предпочитаю это (я использую машинописный текст, отсюда «Let» и =>):

let obj = this.$filter('filter')(this.CommissionTypes, (item) =>{ 
             return item.commission_type_id === 6;
           })[0];

Я делаю это, потому что в какой-то момент мне может понадобиться получить дополнительную информацию из этих отфильтрованных данных и т.д ... наличие функции прямо там как бы оставляет капот открытым.

Дэниел Моррис
источник
У меня была такая же ошибка, как и у вас, спасибо за подсказку с третьим логическим параметром. Не знал об этом.
Георг Лебер,
12

если вы хотите создать отдельный список результатов в контроллере, вы можете применить фильтр

function MyCtrl($scope, filterFilter) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
  //create a filtered array of results 
  //with grade 'C' or subjects that have been failed
  $scope.failedSubjects = filterFilter($scope.results.subjects, {'grade':'C'});
}

Затем вы можете ссылаться на failedSubjects так же, как и на объект результатов.

вы можете прочитать об этом здесь https://docs.angularjs.org/guide/filter

поскольку этот ответ angular обновил документацию, теперь они рекомендуют вызывать фильтр

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});
Киран
источник
что такое filterFilter? это какая-то услуга или директива? где код для filterFilter?
Mou
это угловой сервис. Взгляните на первый пример по ссылке выше. (в файле scripts.js)
Киран
хотя они изменили документацию filter Filter все еще работает ..
Киран
5

Если вы используете ES6, вы можете:

var sample = [1, 2, 3]

var result = sample.filter(elem => elem !== 2)

/* output */
[1, 3]

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

Диего Венансио
источник
4

Вы также можете использовать функции с $filter('filter'):

var foo = $filter('filter')($scope.results.subjects, function (item) {
  return item.grade !== 'A';
});
Нелу
источник
0

Применение того же фильтра в HTML с несколькими столбцами, просто пример:

 variable = (array | filter : {Lookup1Id : subject.Lookup1Id, Lookup2Id : subject.Lookup2Id} : true)
Амай Кулкарни
источник