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

122

Si j'ai un tableau d'objets et que je souhaite lier le modèle angulaire à une propriété de l'un des éléments en fonction d'un filtre, comment puis-je faire cela? 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>

Manette:

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 du sujet avec une note «C», mais je ne veux pas lier le modèle à la note ; Je veux le lier au titre de la matière qui a la note «C».

Est-ce possible, et si oui, comment cela se fait-il?

Bernhard Hofmann
la source

Réponses:

127
<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>
JB Nizet
la source
1
Je vois où tu veux en venir, mais je ne voulais vraiment pas de répéteur. La propriété sur laquelle je vais filtrer est une colonne d'identité, elle est donc unique. Mais je vois que ce serait la bonne façon de résoudre le problème générique.
Bernhard Hofmann
1
ceci est un tutoriel pour les italiens :) dev.stasbranger.com/post/77190983049/…
Silvio Troia
10
cela a été très utile, et pour l'inverse (tout autre que C), cela fonctionnerait:filter:{grade:'!'+'C'}
pulkitsinghal
2
Pouvez-vous faire la même chose avec un grade array? Dans mon cas, je construis mon tableau de notes à partir d'une arborescence et je veux filtrer le résultat pour ceux du tableau.
Juan Carlos Oropeza
157

Vous pouvez utiliser le filtre «filtre» de votre contrôleur pour obtenir toutes les notes «C». Obtenir le premier élément du tableau de résultats vous donnera le titre du sujet qui a la note «C».

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

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

La même chose avec l'ES6 ordinaire:

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]
Oliver
la source
Je suis désolé de ne pas suivre ce deuxième filtre («filtre») pouvez-vous expliquer celui-là un peu plus?
Winnemucca
1
@stevek C'est le nom du filtre. La méthode filter () vous donne le filtre. C'est juste que le filtre est appelé filtre car il filtre un tableau. Cela ressemblerait à ceci avec le filtre de devise: $ filter ('currency') (amount, symbol, fractionSize) Consultez la documentation ici: docs.angularjs.org/api/ng/filter
Oliver
61

Voici un JSBin modifié avec un exemple de travail:

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">
lukeatdesignworks
la source
1
C'est la vraie affaire. C'est le pouvoir. Ceci est le chemin. Je suis allé avec ça et maintenant je suis content.
user1576978
13

veuillez noter que si vous utilisez $ filter comme ceci:

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

et vous aviez une autre note pour, Oh je ne sais pas, CC ou AC ou C + ou CCC il les attire. vous devez ajouter une exigence pour une correspondance exacte:

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

Cela m'a vraiment tué quand je saisissais des détails de commission comme celui-ci:

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

seulement être appelé pour un bogue parce qu'il tirait l'ID de commission 56 au lieu de 6.

L'ajout du vrai force une correspondance exacte.

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

Pourtant, je préfère cela (j'utilise du dactylographié, d'où le "Let" et =>):

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

Je fais cela parce que, à un moment donné, je pourrais vouloir obtenir plus d'informations à partir de ces données filtrées, etc ... avoir la fonction juste à l'intérieur laisse le capot ouvert.

Daniel Morris
la source
J'ai eu la même erreur que vous, merci pour l'indice avec le troisième paramètre booléen. J'en étais pas au courant.
Georg Leber
12

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

Ensuite, vous pouvez référencer les objets ayant échoué de la même manière que vous référeneriez l' objet de résultats

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

depuis cette réponse angular ont mis à jour la documentation, ils recommandent maintenant d'appeler le filtre

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});
Kieran
la source
qu'est-ce que filterFilter? est-ce un service ou une directive? où est le code pour filterFilter?
Mou
c'est un service anguleux. Jetez un œil au premier exemple dans le lien ci-dessus. (dans le fichier scripts.js)
Kieran
bien qu'ils aient changé la documentation filterFilter fonctionne toujours ..
Kieran
4

Vous pouvez également utiliser des fonctions avec $filter('filter'):

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

Si vous utilisez ES6, vous pouvez:

var sample = [1, 2, 3]

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

/* output */
[1, 3]

Notez également que le filtre ne met pas à jour le tableau existant, il renverra un nouveau tableau filtré à chaque fois.

Diego Venâncio
la source
0

Appliquer le même filtre en HTML avec plusieurs colonnes, exemple:

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