web-dev-qa-db-fra.com

AngularJS - Comment obtenir une référence de résultat filtrée par ngRepeat

J'utilise une directive ng-repeat avec un filtre comme celui-ci:

ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4"

et je peux voir les résultats rendus bien; Maintenant, je veux exécuter une logique sur ce résultat dans mon contrôleur. La question est de savoir comment puis-je récupérer la référence des éléments de résultat?

Mise à jour:


Juste pour clarifier: j'essaie de créer une auto-complétion, j'ai cette entrée:

<input id="queryInput" ng-model="query" type="text" size="30" placeholder="Enter query">

puis les résultats filtrés:

<ul>
   <li  ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4">{{item.name}}</li>
</ul>

maintenant, je veux naviguer dans le résultat et sélectionner l'un des éléments.

125
Shlomi Schwartz

UPDATE : Voici un moyen plus simple que ce qui existait auparavant.

 <input ng-model="query">
 <div ng-repeat="item in (filteredItems = (items | orderBy:'order_prop' | filter:query | limitTo:4))">
   {{item}}
 </div>

Ensuite $scope.filteredItems est accessible.

265
Andrew Joslin

Voici la version de filtre de la solution d'Andy Joslin.

Mise à jour: RUPTURE DU CHANGEMENT. A partir de la version 1.3.0-beta.19 ( this commit ), les filtres n'ont pas de contexte et this sera lié à la portée globale. Vous pouvez soit passer le contexte en tant qu'argument, soit utiliser la nouvelle syntaxe d'aliasing dans ngRepeat , 1.3.0-beta.17 +.

// pre 1.3.0-beta.19
yourModule.filter("as", function($parse) {
  return function(value, path) {
    return $parse(path).assign(this, value);
  };
});

// 1.3.0-beta.19+
yourModule.filter("as", function($parse) {
  return function(value, context, path) {
    return $parse(path).assign(context, value);
  };
});

Alors à votre avis

<!-- pre 1.3.0-beta.19 -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.19+ -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:this:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.17+ ngRepeat aliasing -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 as filteredItems">
 {{item}}
</div>

Ce qui vous donne accès à $scope.filteredItems.

30
kevinjamesus86

Essayez quelque chose comme ça, le problème avec ng-repeat est qu’il crée une portée enfant à cause de cela, vous ne pouvez pas y accéder.

éléments filtrants

du contrôleur

<li ng-repeat="doc in $parent.filteritems = (docs | filter:searchitems)" ></li>
23

Mise à jour:

Même après 1.3.0. si vous voulez le placer dans la portée du contrôleur ou du parent, vous ne pouvez pas le faire avec la syntaxe as. Par exemple si j'ai le code suivant:

<div>{{labelResults}}</div>
<li ng-repeat="label in (labels | filter:query | as labelResults)">
</div>

ce qui précède pas fonctionne. La solution consiste à utiliser le $ parent comme suit:

<li ng-repeat="label in ($parent.labelResults = (labels | filter:query))">
15
Gal Bracha

J'ai proposé une version légèrement meilleure de la solution d'Andy. Dans sa solution, ng-repeat place une surveillance sur l'expression contenant l'assignation. Chaque boucle de digestion évaluera cette expression et affectera le résultat à la variable scope.

Le problème avec cette solution est que vous pouvez rencontrer des problèmes d’affectation si vous vous trouvez dans une portée enfant. C'est la même raison pour laquelle vous devriez avoir un point dans ng-model .

L'autre chose que je n'aime pas dans cette solution, c'est qu'elle enterre la définition du tableau filtré quelque part dans le balisage de la vue. Si elle est utilisée à plusieurs endroits de votre vue ou de votre contrôleur, cela peut prêter à confusion.

Une solution plus simple consiste simplement à placer une montre dans votre contrôleur sur une fonction qui effectue l'affectation:

$scope.$watch(function () {
    $scope.filteredItems = $scope.$eval("items | orderBy:'order_prop' | filter:query | limitTo:4");
});

Cette fonction sera évaluée à chaque cycle de digestion afin que les performances soient comparables à celles de la solution d'Andy. Vous pouvez également ajouter un nombre quelconque d'assignations dans la fonction pour les conserver toutes au même endroit plutôt que de les disperser dans la vue.

Dans la vue, vous utiliseriez simplement la liste filtrée directement:

<ul>
    <li  ng-repeat="item in filteredItems">{{item.name}}</li>
</ul>

Voici un violon où cela est montré dans un scénario plus compliqué.

10
Dave Johnson