Como usar ng-repeat sem um elemento html

Eu preciso usar ng-repeat (em AngularJS) para listar todos os elementos em uma matriz.

A complicação é que cada elemento da matriz se transformará em uma, duas ou três linhas de uma tabela.

Não consigo criar html válido, se ng-repeat for usado em um elemento, já que nenhum tipo de elemento de repetição é permitido entre

e

.

Por exemplo, se eu usasse ng-repeat em , eu teria:

  ... ......... ......

Qual é o html inválido.

Mas o que preciso ser gerado é:

 ..................

onde a primeira linha foi gerada pelo primeiro elemento da matriz, os próximos três pelo segundo e o quinto e sexto pelo último elemento da matriz.

Como posso usar ng-repeat de tal forma que o elemento html ao qual ele está ligado ‘desaparece’ durante a renderização?

Ou existe outra solução para isso?


Esclarecimento: A estrutura gerada deve se parecer abaixo. Cada elemento da matriz pode gerar entre 1-3 linhas da tabela. A resposta deve idealmente suportar 0-n linhas por elemento de matriz.

 
One row item
Three row item
Some product details
Customer ratings
Two row item
Full description

Atualização: Se você estiver usando o Angular 1.2+, use ng-repeat-start . Veja a resposta do @jmagnusson.

Caso contrário, que tal colocar a ng-repeat no corpo? (AFAIK, não há problema em ter vários

s em uma única tabela.)

   {{item}}   

A partir do AngularJS 1.2 existe uma diretiva chamada ng-repeat-start que faz exatamente o que você pede. Veja minha resposta nesta pergunta para uma descrição de como usá-lo.

Se você usar ng> 1.2, aqui está um exemplo do uso de ng-repeat-start/end sem gerar tags desnecessárias:

       
{{elem.k}} {{elem.v[0]}}
{{v}}

Você pode querer nivelar os dados dentro do seu 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; } } 

E então no HTML:

 
{{item}}

O acima está correto, mas para uma resposta mais geral, não é suficiente. Eu precisava aninhar ng-repeat, mas permanecer no mesmo nível de html, ou seja, escrever os elementos no mesmo pai. A matriz de tags contém tag (s) que também possuem uma matriz de tags. Na verdade é uma tree.

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

Então aqui está o que eu finalmente fiz.

 
{{tag1}},
{{tag2}},

Observe o ng-if = “false” que oculta as divs de início e fim.

Deve imprimir

nome1, nome1_1, nome1_2, nome2, nome2_1, nome2_2,

Eu gostaria apenas de comentar, mas minha reputação ainda está faltando. Então, estou adicionando outra solução que resolve o problema também. Eu realmente gostaria de refutar a afirmação feita pelo @bmoeskau de que resolver este problema requer uma solução ‘hacky na melhor das hipóteses’, e como isso surgiu recentemente em uma discussão, mesmo que este post tenha 2 anos, gostaria de adicionar possui dois centavos:

Como o @btford apontou, parece que você está tentando transformar uma estrutura recursiva em uma lista, portanto, você deve achatar essa estrutura em uma lista primeiro. Sua solução faz isso, mas há uma opinião de que chamar a function dentro do modelo é deselegante. se isso for verdade (honestamente, eu não sei), não seria necessário apenas executar a function no controlador em vez da diretiva?

De qualquer forma, o seu html requer uma lista, então o escopo que renderiza deve ter essa lista para trabalhar. você simplesmente tem que achatar a estrutura dentro do seu controlador. Uma vez que você tenha uma matriz $ scope.rows, você pode gerar a tabela com uma única e simples repetição de ng. Sem hacking, sem deselegância, simplesmente como foi projetado para funcionar.

Diretivas angulares não faltam funcionalidade. Eles simplesmente forçam você a escrever um html válido. Um colega meu teve um problema semelhante, citando @bmoeskau em apoio a críticas sobre resources de modelagem / renderização de angulos. Ao olhar para o problema exato, descobriu-se que ele simplesmente queria gerar uma tag aberta, em seguida, uma tag de fechamento em algum outro lugar, etc., como nos bons e velhos tempos, quando combinávamos nosso html com strings … certo? não.

como para achatar a estrutura em uma lista, aqui está outra solução:

 // 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'] 

isso funcionará para qualquer estrutura semelhante a tree que tenha subitens. Se você quiser o item inteiro em vez de uma propriedade, poderá encurtar ainda mais a function de nivelamento.

espero que ajude.

você pode usar a function underscore flatten $scope.myData= _.flatten($scope.myData);

 
{{data[0].foo}}
{{d.bar}}
{{d.lol}}

Eu acho que isso é válido 🙂