without tag start for example array angularjs

angularjs - tag - ng-repeat table



Cómo usar ng-repeat sin un elemento html (8)

Necesito usar ng-repeat (en AngularJS) para listar 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 se usa ng-repeat en un elemento, ya que no se permite ningún tipo de elemento repetitivo entre <tbody> y <tr> .

Por ejemplo, si utilicé ng-repeat en <span> , obtengo:

<table> <tbody> <span> <tr>...</tr> </span> <span> <tr>...</tr> <tr>...</tr> <tr>...</tr> </span> <span> <tr>...</tr> <tr>...</tr> </span> </tbody> </table>

¿Cuál es html no válido?

Pero lo que necesito generar 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, los siguientes tres por la segunda y la quinta y la 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 ''desaparece'' durante la representación?

¿O hay otra solución para esto?

Aclaración: la estructura generada debería verse a continuación. Cada elemento de matriz puede generar entre 1-3 filas de la tabla. La respuesta debería ser compatible con 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>


A partir de AngularJS 1.2 hay una directiva llamada ng-repeat-start que hace exactamente lo que usted solicita. Vea mi respuesta en esta pregunta para una descripción de cómo usarla.


Es posible que desee aplanar los datos dentro de su controlador:

function MyCtrl ($scope) { $scope.myData = [[1,2,3], [4,5,6], [7,8,9]]; $scope.flattened = function () { var flat = []; $scope.myData.forEach(function (item) { flat.concat(item); } return flat; } }

Y luego en el HTML:

<table> <tbody> <tr ng-repeat="item in flattened()"><td>{{item}}</td></tr> </tbody> </table>


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, es decir, 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.

[{ name:''name1'', tags: [ { name: ''name1_1'', tags: []}, { name: ''name1_2'', tags: []} ]}, { name:''name2'', tags: [ { name: ''name2_1'', tags: []}, { name: ''name2_2'', tags: []} ]} ]

Así que aquí es lo que finalmente hice.

<div ng-repeat-start="tag1 in tags" ng-if="false"></div> {{tag1}}, <div ng-repeat-start="tag2 in tag1.tags" ng-if="false"></div> {{tag2}}, <div ng-repeat-end ng-if="false"></div> <div ng-repeat-end ng-if="false"></div>

Tenga en cuenta el ng-if = "false" que oculta los divs de inicio y fin.

Debe imprimir

name1, name1_1, name1_2, name2, name2_1, name2_2,


Me gustaría simplemente comentar, pero mi reputación aún me falta. Así que estoy agregando otra solución que también resuelve el problema. Realmente me gustaría refutar la afirmació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 poseer dos centavos:

Como ha señalado @btford, parece que intenta convertir una estructura recursiva en una lista, por lo que debe aplanar esa estructura primero en una lista. Su solución lo hace, pero hay una opinión de que llamar a la función dentro de la plantilla es poco elegante. si eso es cierto (honestamente, no lo sé) ¿no sería necesario 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 la 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 simple y simple repetición ng. Sin piratería, sin inelegancia, simplemente la forma en que fue diseñado para funcionar.

Las directivas de Angulars no carecen de funcionalidad. Simplemente te obligan a escribir un html válido. Un colega mío tenía un problema similar, citando a @bmoeskau en apoyo de las críticas sobre las características de procesamiento de plantillas de angulares. Al ver el problema exacto, resultó que simplemente quería generar una etiqueta abierta, luego una etiqueta cercana en otro lugar, etc., como en los viejos tiempos cuando concatábamos nuestro html de cadenas ... ¿verdad? no.

en cuanto a aplanar la estructura en una lista, aquí hay otra solución:

// assume the following structure var structure = [ { name: ''item1'', subitems: [ { name: ''item2'', subitems: [ ], } ], } ]; var flattened = structure.reduce((function(prop,resultprop){ var f = function(p,c,i,a){ p.push(c[resultprop]); if (c[prop] && c[prop].length > 0 ) p = c[prop].reduce(f,p); return p; } return f; })(''subitems'',''name''),[]); // flattened now is a list: [''item1'', ''item2'']

esto funcionará para cualquier estructura tipo árbol que tenga sub elementos. Si desea el artículo completo en lugar de una propiedad, puede acortar la función de aplanamiento aún más.

Espero que ayude.


Si usa ng> 1.2, aquí hay un ejemplo de uso de ng-repeat-start/end sin generar etiquetas innecesarias:

<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <script> angular.module(''mApp'', []); </script> </head> <body ng-app="mApp"> <table border="1" width="100%"> <tr ng-if="0" ng-repeat-start="elem in [{k: ''A'', v: [''a1'',''a2'']}, {k: ''B'', v: [''b1'']}, {k: ''C'', v: [''c1'',''c2'',''c3'']}]"></tr> <tr> <td rowspan="{{elem.v.length}}">{{elem.k}}</td> <td>{{elem.v[0]}}</td> </tr> <tr ng-repeat="v in elem.v" ng-if="!$first"> <td>{{v}}</td> </tr> <tr ng-if="0" ng-repeat-end></tr> </table> </body> </html>

El punto importante: para las etiquetas utilizadas para ng-repeat-start y ng-repeat-end set ng-if="0" , para que no se inserten en la página. De esta forma, el contenido interno se manejará exactamente como en knockoutjs (usando comandos en <!--...--> ), y no habrá basura.


puede usar la función de aplanar subrayado $scope.myData= _.flatten($scope.myData);


Actualización: si está usando Angular 1.2+, use ng-repeat-start . Ver la respuesta de @ jmagnusson.

De lo contrario, ¿qué hay de poner la repetición ng en tbody? (AFAIK, está bien tener múltiples <tbody> s en una sola mesa).

<tbody ng-repeat="row in array"> <tr ng-repeat="item in row"> <td>{{item}}</td> </tr> </tbody>


<table> <tbody> <tr><td>{{data[0].foo}}</td></tr> <tr ng-repeat="d in data[1]"><td>{{d.bar}}</td></tr> <tr ng-repeat="d in data[2]"><td>{{d.lol}}</td></tr> </tbody> </table>

Creo que esto es válido :)