J'ai un problème qui s'est présenté plus d'une fois ces derniers temps, et je me demande quelle est la meilleure façon de procéder. Pour faire simple :
J'ai des données affichées dans un ng-repeat, triées par un élément particulier. Disons qu'elles sont triées par Nom, par exemple. Mon objectif est d'avoir des en-têtes aux coupures de lettres dans la liste alphabétique :
----A----
Abe Lincoln
Adam Smith
----B----
Barack Obama
Barry Zuckercorn
----C----
...
et ainsi de suite.
Les choses que j'ai essayées sont les suivantes :
- Le contrôleur doit reconstruire entièrement les données du modèle au fur et à mesure qu'elles arrivent, en les plaçant manuellement dans un tableau de groupes de lettres. Par exemple, mon service a un tableau de "posts" et mon contrôleur, au fur et à mesure que le service se met à jour, mélange manuellement ces "posts" dans un tableau de "letterGroups". Il est alors possible d'avoir simplement deux ng-repeats imbriqués
Cependant, cette méthode repose sur une manipulation importante des données, et il n'est pas facile de modifier à la volée l'ordre de tri des données.
- Lorsque le modèle est mis à jour, le contrôleur doit "doper" les données en les parcourant manuellement, en vérifiant si la lettre change et en ajoutant une propriété "header" à cet élément (
post.header = true
). Le ng-repeat peut alors vérifier si l'élément sur lequel il se trouve est un en-tête, et utiliser ng-if pour insérer quelque chose d'autre dans le DOM.
Cela semble un peu plus propre, mais en raison de la façon dont ng-repeat fonctionne, l'élément d'en-tête doit être "inclus" au même niveau que l'élément ng-repeating. Par exemple, si vous faites le ng-repeat sur <tr>
cela signifierait qu'il serait impossible d'insérer une autre <tr>
pour l'en-tête, puisque l'élément spécial doit apparaître à l'intérieur el <tr>
Enfin, dans le même ordre d'idées que ci-dessus :
- Demander au contrôleur de maintenir une liste d'"index de clés" - cette méthode présente l'avantage de ne pas modifier les données comme la deuxième méthode ci-dessus, mais fonctionne généralement de la même manière.
EDIT :
J'ai écrit un article de blog aquí expliquant comment j'ai finalement géré ce problème - grâce à la discussion Google Groups liée à la réponse de Ian ci-dessous.