132 votes

Comment filtrer un tableau avec AngularJS et utiliser une propriété de l'objet filtré comme attribut ng-model ?

Si j'ai un tableau d'objets et que je veux lier le modèle Angular à une propriété de l'un des éléments en fonction d'un filtre, comment puis-je faire ? Je peux mieux expliquer avec un exemple concret :

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>

Contrôleur :

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

Je veux filtrer la deuxième entrée sur le sujet avec une note 'C', mais je ne veux pas lier le modèle à l'entrée 'C'. grade ; je veux le lier à la titre de la matière qui a obtenu la note "C".

Est-ce possible et, dans l'affirmative, comment s'y prendre ?

164voto

Olivér Kovács Points 1471

Vous pouvez utiliser le filtre "filter" dans votre contrôleur pour obtenir toutes les notes "C". En récupérant le premier élément du tableau de résultats, vous obtiendrez l'information suivante titre de la matière qui a obtenu la note "C".

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

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

Il en va de même pour l'ES6 ordinaire :

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]

138voto

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

63voto

lukeatdesignworks Points 671

Voici un JSBin modifié avec un échantillon fonctionnel :

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

Voici ce que j'ai fait avec les filtres dans l'entrée :

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

17voto

Daniel Morris Points 139

Veuillez noter que si vous utilisez $filter comme ceci :

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

et qu'il vous arrive d'avoir une autre note pour, oh je ne sais pas, CC ou AC ou C+ ou CCC, il les intègre. vous devez ajouter une exigence pour une correspondance exacte :

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

Ça m'a vraiment tué quand j'ai fait des détails de commission comme ça :

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

n'a été appelé pour un bug que parce qu'il faisait entrer l'ID de la commission 56 au lieu de 6.

L'ajout de "true" force une correspondance exacte.

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

Pourtant, je préfère encore ceci (j'utilise le typecript, d'où le "Let" et =>) :

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

Je le fais parce que, à un moment donné, je pourrais vouloir obtenir plus d'informations à partir de ces données filtrées, etc... le fait d'avoir la fonction directement là laisse en quelque sorte le capot ouvert.

13voto

Kieran Points 4268

Si vous voulez créer une liste séparée de résultats dans le contrôleur, vous pouvez appliquer un filtre.

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

Vous pouvez alors faire référence failedSubjects de la même manière que vous feriez référence au résultats objet

vous pouvez en savoir plus à ce sujet ici https://docs.angularjs.org/guide/filter

Depuis cette réponse, Angular a mis à jour la documentation et recommande maintenant d'appeler le filtre.

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X