J'ai besoin d'utiliser ng-repeat
(dans AngularJS) pour lister tous les éléments d'un tableau.
La complication est que chaque élément du tableau se transforme en une, deux ou trois lignes d'une table.
Je ne peux pas créer de code HTML valide, si ng-repeat
est utilisé sur un élément, car aucun type d'élément répétitif n'est autorisé entre <tbody>
et <tr>
.
Par exemple, si j'utilisais ng-repeat sur <span>
, j'obtiendrais:
<table>
<tbody>
<span>
<tr>...</tr>
</span>
<span>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</span>
<span>
<tr>...</tr>
<tr>...</tr>
</span>
</tbody>
</table>
Ce qui est du HTML invalide.
Mais ce dont j'ai besoin pour être généré, c'est:
<table>
<tbody>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
où la première ligne a été générée par le premier élément du tableau, les trois suivants par le deuxième et le cinquième et le sixième par le dernier élément du tableau.
Comment puis-je utiliser ng-repeat de telle sorte que l'élément html auquel il est lié «disparaisse» lors du rendu?
Ou y a-t-il une autre solution à cela?
Clarification: la structure générée doit ressembler à celle ci-dessous. Chaque élément du tableau peut générer entre 1 et 3 lignes du tableau. La réponse devrait idéalement prendre en charge 0-n lignes par élément de tableau.
<table>
<tbody>
<!-- array element 0 -->
<tr>
<td>One row item</td>
</tr>
<!-- array element 1 -->
<tr>
<td>Three row item</td>
</tr>
<tr>
<td>Some product details</td>
</tr>
<tr>
<td>Customer ratings</td>
</tr>
<!-- array element 2 -->
<tr>
<td>Two row item</td>
</tr>
<tr>
<td>Full description</td>
</tr>
</tbody>
</table>
tr
, j'obtiendrais une ligne par élément de tableau, pour autant que je sache.tr
s qui sont générés par un élément du tableau n'ont pas la même structure.Réponses:
Mise à jour: si vous utilisez Angular 1.2+, utilisez ng-repeat-start . Voir la réponse de @ jmagnusson.
Sinon, que diriez-vous de mettre le ng-repeat sur tbody? (AFAIK, il est normal d'avoir plusieurs <tbody> dans une seule table.)
la source
Depuis AngularJS 1.2, il existe une directive appelée
ng-repeat-start
qui fait exactement ce que vous demandez. Voir ma réponse dans cette question pour une description de son utilisation.la source
Si vous utilisez ng> 1.2, voici un exemple d'utilisation
ng-repeat-start/end
sans générer de balises inutiles:Le point important: pour les balises utilisées pour
ng-repeat-start
etng-repeat-end
définiesng-if="0"
, ne pas laisser s'insérer dans la page. De cette façon, le contenu interne sera traité exactement comme dans knockoutjs (en utilisant les commandes in<!--...-->
), et il n'y aura pas de déchets.la source
Vous souhaiterez peut-être aplatir les données de votre contrôleur:
Et puis dans le HTML:
la source
ng-repeat-start
,ng-repeat-end
casser ma conception, donc la solution était de créer une variable supplémentaire en ajoutant cet objet séparateur avant chaque élément et d'itérer la nouvelle var:<div class="c477_group"> <div class="c477_group_item" ng-repeat="item in itemsWithSeparator" ng-switch="item.id" ng-class="{'-divider' : item.id == 'SEPARATOR'}"> <div class="c478" ng-switch-when="FAS"/> <div class="c478" ng-switch-when="SEPARATOR" /> <div class="c479" ng-switch-default /> </div> </div>
Ce qui précède est correct mais pour une réponse plus générale, cela ne suffit pas. J'avais besoin d'imbriquer ng-repeat, mais restez au même niveau html, c'est-à-dire écrire les éléments dans le même parent. Le tableau de balises contient des balises qui ont également un tableau de balises. C'est en fait un arbre.
Voici donc ce que j'ai finalement fait.
Notez le ng-if = "false" qui masque les div de début et de fin.
Il devrait imprimer
nom1, nom1_1, nom1_2, nom2, nom2_1, nom2_2,
la source
Je voudrais juste faire un commentaire, mais ma réputation fait encore défaut. Donc, j'ajoute une autre solution qui résout également le problème. Je voudrais vraiment réfuter l'affirmation de @bmoeskau selon laquelle la résolution de ce problème nécessite une solution de `` piratage au mieux '', et comme cela est apparu récemment dans une discussion, même si ce message a 2 ans, j'aimerais ajouter mon posséder deux cents:
Comme @btford l'a souligné, vous semblez essayer de transformer une structure récursive en liste, vous devez donc d'abord aplatir cette structure en liste. Sa solution fait cela, mais il y a une opinion selon laquelle l'appel de la fonction à l'intérieur du modèle est inélégant. si c'est vrai (honnêtement, je ne sais pas) cela ne nécessiterait-il pas simplement d'exécuter la fonction dans le contrôleur plutôt que la directive?
Dans tous les cas, votre html nécessite une liste, donc la portée qui le rend devrait avoir cette liste pour travailler avec. vous devez simplement aplatir la structure à l'intérieur de votre contrôleur. une fois que vous avez un tableau $ scope.rows, vous pouvez générer la table avec une seule et simple répétition ng. Pas de piratage, pas d'inélégance, simplement la façon dont il a été conçu pour fonctionner.
Les directives Angulars ne manquent pas de fonctionnalités. Ils vous obligent simplement à écrire du code HTML valide. Un de mes collègues a eu un problème similaire, citant @bmoeskau à l'appui des critiques sur les fonctionnalités de modélisation / rendu angulaires. En regardant le problème exact, il s'est avéré qu'il voulait simplement générer une balise ouverte, puis une balise de fermeture ailleurs, etc., tout comme au bon vieux temps où nous concattrions notre html à partir de chaînes ... non? non.
Quant à l'aplatissement de la structure en une liste, voici une autre solution:
cela fonctionnera pour toute structure arborescente comportant des sous-éléments. Si vous voulez l'élément entier au lieu d'une propriété, vous pouvez raccourcir encore plus la fonction d'aplatissement.
J'espère que cela pourra aider.
la source
pour une solution qui fonctionne vraiment
html
ajouter une directive angular.js
pour une brève explication,
ng-repeat se lie à l'
<remove>
élément et boucle comme il se doit, et parce que nous avons utilisé ng-repeat-start / ng-repeat-end, il boucle un bloc de html pas seulement un élément.puis la directive remove personnalisée place les
<remove>
éléments de début et de fin avec<!--removed element-->
la source
Je pense que c'est valable :)
la source