Jak przefiltrować tablicę za pomocą AngularJS i użyć właściwości przefiltrowanego obiektu jako atrybutu ng-model?

122

Jeśli mam tablicę obiektów i chcę powiązać model Angular z właściwością jednego z elementów na podstawie filtru, jak mam to zrobić? Mogę lepiej wyjaśnić na konkretnym przykładzie:

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>

Kontroler:

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

Chcę odfiltrować drugie wejście do przedmiotu z oceną „C”, ale nie chcę wiązać modelu z oceną ; Chcę to powiązać z tytułem przedmiotu z oceną „C”.

Czy to możliwe, a jeśli tak, to jak to się robi?

Bernhard Hofmann
źródło

Odpowiedzi:

127
<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>
JB Nizet
źródło
1
Rozumiem, dokąd z tym zmierzasz, ale naprawdę nie chciałem repeatera. Właściwość, według której będę filtrować, to kolumna tożsamości, więc jest unikalna. Ale widzę, że byłby to właściwy sposób rozwiązania ogólnego problemu.
Bernhard Hofmann
1
to jest poradnik dla Włochów
Silvio Troia
10
to było bardzo pomocne, a dla odwrotności (wszystko inne niż C), zadziałałoby:filter:{grade:'!'+'C'}
pulkitsinghal
2
Czy możesz zrobić to samo z grade array? W moim przypadku tworzę tablicę ocen z widoku drzewa i chcę przefiltrować wynik dla tych w tablicy.
Juan Carlos Oropeza
157

Możesz użyć filtra „filter” w kontrolerze, aby uzyskać wszystkie oceny „C”. Uzyskanie pierwszego elementu tablicy wyników da ci tytuł przedmiotu z oceną „C”.

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

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

To samo dotyczy zwykłego ES6:

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]
Oliver
źródło
Przepraszam, nie śledzę tego drugiego filtra („filtru”). Czy możesz wyjaśnić to trochę więcej?
Winnemucca
1
@stevek To nazwa filtra. Metoda filter () podaje filtr. Po prostu ten filtr nazywa się filtrem, ponieważ filtruje tablicę. Z filtrem walutowym wyglądałoby to tak: $ filter ('currency') (amount, symbol, fractionSize) Sprawdź dokumentację tutaj: docs.angularjs.org/api/ng/filter
Oliver
61

Oto zmodyfikowany JSBin z próbką roboczą:

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

Oto co zrobiłem z filtrami na wejściu:

<input ng-model="(results.subjects | filter:{grade:'C'})[0].title">
lukeatdesignworks
źródło
1
To jest prawdziwa okazja. To jest moc. To jest sposób. Poszedłem z tym i teraz jestem szczęśliwy.
user1576978
13

uwaga, jeśli używasz $ filter w ten sposób:

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

i tak się złożyło, że miałeś inną ocenę za, nie wiem, CC lub AC lub C + lub CCC to ciągnie ich do. musisz dołączyć wymaganie dotyczące dopasowania ścisłego:

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

To naprawdę mnie zabiło, kiedy wyciągałem niektóre szczegóły dotyczące prowizji, takie jak ten:

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

Zostajesz wezwany tylko z powodu błędu, ponieważ pobierał on identyfikator prowizji 56, a nie 6.

Dokładne dopasowanie prawdziwych sił.

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

Mimo to wolę to (używam maszynopisu, stąd „Let” i =>):

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

Robię to, ponieważ w pewnym momencie mógłbym chcieć uzyskać więcej informacji z tych przefiltrowanych danych itp. ... posiadanie tej funkcji powoduje, że maska ​​jest otwarta.

Daniel Morris
źródło
Miałem taki sam błąd jak Ty, dzięki za podpowiedź z trzecim parametrem boolowskim. Nie był tego świadomy.
Georg Leber,
12

jeśli chciałeś stworzyć osobną listę wyników w kontrolerze, możesz zastosować filtr

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

Następnie możesz odwoływać się do failedSubjects w taki sam sposób, jak do obiektu results

możesz przeczytać więcej na ten temat tutaj https://docs.angularjs.org/guide/filter

ponieważ ta odpowiedź angular zaktualizowała dokumentację, teraz zaleca wywołanie filtra

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});
Kieran
źródło
co to jest filterFilter? czy jest to jakaś usługa lub dyrektywa? gdzie jest kod filterFilter?
Mou
jest to usługa kątowa. Spójrz na pierwszy przykład w powyższym linku. (w pliku scripts.js)
Kieran
chociaż zmienili dokumentację filterFilter nadal działa ..
Kieran
4

Możesz także używać funkcji z $filter('filter'):

var foo = $filter('filter')($scope.results.subjects, function (item) {
  return item.grade !== 'A';
});
Nelu
źródło
4

Jeśli używasz ES6, możesz:

var sample = [1, 2, 3]

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

/* output */
[1, 3]

Zwróć również uwagę, że filtr nie aktualizuje istniejącej tablicy, za każdym razem zwróci nową przefiltrowaną tablicę.

Diego Venâncio
źródło
0

Stosowanie tego samego filtru w HTML z wieloma kolumnami, tylko przykład:

 variable = (array | filter : {Lookup1Id : subject.Lookup1Id, Lookup2Id : subject.Lookup2Id} : true)
Amay Kulkarni
źródło