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

Если у меня есть массив объектов, и я хочу привязать модель 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", но я не хочу привязывать модель к классу; Я хочу привязать его к названию темы, имеющей оценку "C".

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

Ответ 1

<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>

Ответ 2

Вы можете использовать фильтр "фильтр" в вашем контроллере, чтобы получить все оценки "С". Получение первого элемента массива результатов даст вам название объекта, имеющего оценку "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]

Ответ 3

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

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

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

<input ng-model="(results.subjects | filter:{grade:'C'})[0].title">

Ответ 4

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

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 так же, как вы ссылаетесь на объект results

вы можете прочитать об этом здесь 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'});

Ответ 5

Обратите внимание, что если вы используете $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];

Тем не менее, я предпочитаю это (я использую typescript, следовательно, "Let" и = > ):

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

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

Ответ 6

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

var foo = $filter('filter')($scope.results.subjects, function (item) {
  return item.grade !== 'A';
});

Ответ 7

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

 variable = (array | filter : {Lookup1Id : subject.Lookup1Id, Lookup2Id : subject.Lookup2Id} : true)

Ответ 8

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

var sample = [1, 2, 3]

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

/* output */
[1, 3]

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