Necesito usar ng-repeat
(en AngularJS) para enumerar todos los elementos en una matriz.
La complicación es que cada elemento de la matriz se transformará en una, dos o tres filas de una tabla.
No puedo crear html válido, si ng-repeat
se usa en un elemento, ya que no se permite ningún tipo de elemento repetitivo entre <tbody>
y <tr>
.
Por ejemplo, si usara ng-repeat on <span>
, obtendría:
<table>
<tbody>
<span>
<tr>...</tr>
</span>
<span>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</span>
<span>
<tr>...</tr>
<tr>...</tr>
</span>
</tbody>
</table>
Que no es válido html.
Pero lo que necesito ser generado es:
<table>
<tbody>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
donde la primera fila ha sido generada por el primer elemento de la matriz, las siguientes tres por el segundo y la quinta y sexta por el último elemento de la matriz.
¿Cómo puedo usar ng-repeat de tal manera que el elemento html al que está vinculado 'desaparezca' durante el renderizado?
¿O hay otra solución para esto?
Aclaración: La estructura generada debería verse como a continuación. Cada elemento de la matriz puede generar entre 1-3 filas de la tabla. La respuesta idealmente debería admitir 0-n filas por elemento de matriz.
<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
, obtendría una fila por elemento de matriz, por lo que entiendo.tr
s que son generados por un elemento de matriz no tienen la misma estructura.Respuestas:
Actualización: si está utilizando Angular 1.2+, use ng-repeat-start . Ver la respuesta de @ jmagnusson.
De lo contrario, ¿qué hay de poner el ng-repeat en tbody? (AFAIK, está bien tener múltiples <tbody> s en una sola tabla).
fuente
A partir de AngularJS 1.2 hay una directiva llamada
ng-repeat-start
que hace exactamente lo que pides. Vea mi respuesta en esta pregunta para obtener una descripción de cómo usarlo.fuente
Si usa ng> 1.2, aquí hay un ejemplo de uso
ng-repeat-start/end
sin generar etiquetas innecesarias:El punto importante: para las etiquetas utilizadas
ng-repeat-start
yng-repeat-end
configuradasng-if="0"
, para que no se inserten en la página. De esta manera, el contenido interno se manejará exactamente como está en knockoutjs (usando comandos en<!--...-->
), y no habrá basura.fuente
Es posible que desee aplanar los datos dentro de su controlador:
Y luego en el HTML:
fuente
ng-repeat-start
,ng-repeat-end
Romper mi diseño, por lo que la solución era crear una variable adicional añadiendo este objeto separador antes de cada elemento e iterar la nueva 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>
Lo anterior es correcto pero para una respuesta más general no es suficiente. Necesitaba anidar ng-repeat, pero permanecer en el mismo nivel html, lo que significa escribir los elementos en el mismo padre. La matriz de etiquetas contiene etiquetas que también tienen una matriz de etiquetas. En realidad es un árbol.
Así que aquí está lo que eventualmente hice.
Tenga en cuenta el ng-if = "false" que oculta los divs de inicio y fin.
Debe imprimir
nombre1, nombre1_1, nombre1_2, nombre2, nombre2_1, nombre2_2,
fuente
Solo me gustaría comentar, pero mi reputación todavía es deficiente. Así que estoy agregando otra solución que resuelve el problema también. Realmente me gustaría refutar la declaración hecha por @bmoeskau de que resolver este problema requiere una solución 'hacky en el mejor de los casos', y dado que esto surgió recientemente en una discusión a pesar de que esta publicación tiene 2 años, me gustaría agregar mi posee dos centavos:
Como ha señalado @btford, parece que estás tratando de convertir una estructura recursiva en una lista, por lo que primero debes aplanar esa estructura en una lista. Su solución hace eso, pero existe la opinión de que llamar a la función dentro de la plantilla no es elegante. si eso es cierto (honestamente, no lo sé), ¿no requeriría ejecutar la función en el controlador en lugar de la directiva?
de cualquier manera, su html requiere una lista, por lo que el alcance que lo representa debe tener esa lista para trabajar. simplemente tiene que aplanar la estructura dentro de su controlador. una vez que tenga una matriz $ scope.rows, puede generar la tabla con una sola y simple ng-repeat. Sin piratería, sin inelegancia, simplemente la forma en que fue diseñado para funcionar.
Las directivas angulares no carecen de funcionalidad. Simplemente te obligan a escribir html válido. Un colega mío tuvo un problema similar, citando a @bmoeskau en apoyo de las críticas sobre las características de plantillas / renderizado de angulares. Al mirar el problema exacto, resultó que simplemente quería generar una etiqueta abierta, luego una etiqueta cerrada en otro lugar, etc., como en los viejos tiempos, cuando concatábamos nuestro html a partir de cadenas ... ¿verdad? No.
En cuanto a aplanar la estructura en una lista, aquí hay otra solución:
esto funcionará para cualquier estructura en forma de árbol que tenga sub ítems. Si desea todo el elemento en lugar de una propiedad, puede acortar aún más la función de aplanamiento.
Espero que ayude.
fuente
para una solución que realmente funciona
html
agregar una directiva angular.js
para una breve explicación,
ng-repeat se une al
<remove>
elemento y se repite como debería, y debido a que hemos usado ng-repeat-start / ng-repeat-end se repite un bloque de html no solo un elemento.entonces la directiva de eliminación personalizada coloca los
<remove>
elementos de inicio y finalización con<!--removed element-->
fuente
Creo que esto es válido :)
fuente