como dividir os dados de repetição ng com três colunas usando bootstrap

Eu estou usando ng-repeat com o meu código eu tenho ‘n’ número de checkbox de texto com base em ng-repeat. Quero alinhar a checkbox de texto com três colunas.

este é meu código

{{$index+1}}.

A abordagem mais confiável e tecnicamente correta é transformar os dados no controlador. Aqui está uma function e uso simples de chunk.

 function chunk(arr, size) { var newArr = []; for (var i=0; i 

Então sua visão ficaria assim:

 
{{item}}

Se você tiver alguma input dentro do ng-repeat , você provavelmente desejará descompactar / reingressar as matrizes à medida que os dados forem modificados ou submetidos. Veja como isso ficaria em um $watch , para que os dados estejam sempre disponíveis no formato mesclado original:

 $scope.$watch('chunkedData', function(val) { $scope.data = [].concat.apply([], val); }, true); // deep watch 

Muitas pessoas preferem fazer isso na exibição com um filtro. Isso é possível, mas só deve ser usado para fins de exibição! Se você adicionar inputs nessa exibição filtrada, isso causará problemas que podem ser resolvidos, mas não são bonitos nem confiáveis .

O problema com esse filtro é que ele retorna novas matrizes aninhadas sempre. Angular está observando o valor de retorno do filtro. Na primeira vez que o filtro é executado, o Angular conhece o valor e, em seguida, executa-o novamente para garantir que ele seja alterado. Se ambos os valores forem iguais, o ciclo é finalizado. Caso contrário, o filtro será triggersdo repetidas vezes até que sejam iguais ou o Angular perceba que um loop de resumo infinito está ocorrendo e será encerrado. Como os novos arrays / objects nesteds não foram rastreados anteriormente pelo Angular, ele sempre vê o valor de retorno como diferente do anterior. Para corrigir esses filtros "instáveis", você deve envolver o filtro em uma function de memoize . lodash tem uma function de memoize e a última versão do lodash também inclui uma function chunk , então podemos criar este filtro de forma muito simples usando módulos npm e compilando o script com o browserify ou webpack .

Lembre-se: exibir apenas! Filtre no controlador se você estiver usando inputs!

Instale o lodash:

 npm install lodash-node 

Crie o filtro:

 var chunk = require('lodash-node/modern/array/chunk'); var memoize = require('lodash-node/modern/function/memoize'); angular.module('myModule', []) .filter('chunk', function() { return memoize(chunk); }); 

E aqui está uma amostra com este filtro:

 
{{($parent.$index*row.length)+$index+1}}. {{item}}

Encomendar itens na vertical

 1 4 2 5 3 6 

Em relação a colunas verticais (lista de cima para baixo) em vez de horizontal (da esquerda para a direita), a implementação exata depende da semântica desejada. As listas que se dividem de forma desigual podem ser distribuídas de maneiras diferentes. Aqui está um jeito:

 
{{item}}
 var data = ['a','b','c','d','e','f','g']; $scope.columns = columnize(data, 3); function columnize(input, cols) { var arr = []; for(i = 0; i < input.length; i++) { var colIdx = i % cols; arr[colIdx] = arr[colIdx] || []; arr[colIdx].push(input[i]); } return arr; } 

No entanto, a maneira mais direta e simples de obter colunas é usar colunas CSS :

 .columns { columns: 3; } 
 
{{item}}

Esta solução é muito simples:

JSON:

 [{id:"1",name:"testA"},{id:"2",name:"test B"},{id:"3",name:"test C"},{id:"4",name:"test D"},{id:"5",name:"test E"}] 

HTML:

 
{{items[$index].id}} {{items[$index].name}} {{items[$index+1].id}} {{items[$index+1].name}} {{items[$index+2].id}} {{items[$index+2].name}}

DEMO no FIDDLE

insira a descrição da imagem aqui

Uma solução limpa e adaptável que não requer manipulação de dados :

O HTML:

 
{{$index+1}}.

O CSS:

 .label { float: left; text-align: left; } .new-row { clear: left; } 

O JavaScript:

 $scope.columnBreak = 3; //Max number of colunms $scope.startNewRow = function (index, count) { return ((index) % count) === 0; }; 

Essa é uma solução simples para renderizar dados em linhas e colunas dinamicamente, sem a necessidade de manipular a matriz de dados que você está tentando exibir. Além disso, se você tentar resize a janela do navegador, poderá ver que a grade se adapta dinamicamente ao tamanho da canvas / div.

(Eu também adicionei um sufixo {{$ index}} ao seu id, pois o ng-repeat tentará criar vários elementos com o mesmo id, se você não o fizer.)

Um exemplo de trabalho semelhante

A resposta do m59 é muito boa. A única coisa que não gosto é que ele usa div para o que poderia ser dados para uma tabela.

Então, em conjunto com o filtro do m59 (resposta em algum lugar acima), aqui está como mostrá-lo em uma tabela.

 
{{item}}

A seguir, uma maneira mais simples:

 

A resposta do Cumulo Nimbus é útil para mim, mas eu quero essa grade envolvida por uma div que pode mostrar a barra de rolagem quando a lista é muito longa.

Para conseguir isso, adicionei style="height:200px; overflow:auto" a um div ao redor da tabela, o que faz com que ele apareça como uma única coluna.

Agora trabalha para o comprimento do array de um.

Eu tenho uma function e armazenei em um serviço para que eu possa usá-lo em todo o meu aplicativo:

Serviço:

 app.service('SplitArrayService', function () { return { SplitArray: function (array, columns) { if (array.length <= columns) { return [array]; }; var rowsNum = Math.ceil(array.length / columns); var rowsArray = new Array(rowsNum); for (var i = 0; i < rowsNum; i++) { var columnsArray = new Array(columns); for (j = 0; j < columns; j++) { var index = i * columns + j; if (index < array.length) { columnsArray[j] = array[index]; } else { break; } } rowsArray[i] = columnsArray; } return rowsArray; } } 

});

Controlador:

 $scope.rows = SplitArrayService.SplitArray($scope.images, 3); //im splitting an array of images into 3 columns 

Marcação:

  

Minha abordagem foi uma mistura de coisas.

Meu objective era ter uma grade adaptando-se ao tamanho da canvas. Eu queria 3 colunas para lg , 2 colunas para sm e md e 1 coluna para xs .

Primeiro, criei a seguinte function de escopo, usando o serviço de $window angular:

 $scope.findColNumberPerRow = function() { var nCols; var width = $window.innerWidth; if (width < 768) { // xs nCols = 1; } else if(width >= 768 && width < 1200) { // sm and md nCols = 2 } else if (width >= 1200) { // lg nCols = 3; } return nCols; }; 

Então, usei a aula proposta pelo @Cumulo Nimbus:

 .new-row { clear: left; } 

No div contendo o ng-repeat , adicionei a diretiva resizable , conforme explicado nesta página , para que toda janela de tempo seja redimensionada, o serviço de $window angular é atualizado com os novos valores.

Em última análise, no div repetido eu tenho:

 ng-repeat="user in users" ng-class="{'new-row': ($index % findColNumberPerRow() === 0) }" 

Por favor, deixe-me saber quaisquer falhas nesta abordagem.

Espero que possa ser útil.

Este exemplo produz um repetidor nested em que os dados externos incluem uma matriz interna que eu queria listar em duas colunas. O conceito seria válido para três ou mais colunas.

Na coluna interna, repito a “linha” até que o limite seja atingido. O limite é determinado pela divisão do comprimento do array de itens pelo número de colunas desejadas, neste caso por dois. O método de divisão fica no controlador e passa o comprimento da matriz atual como um parâmetro. A function fatia de JavaScript (0, array.length / columnCount) aplicou o limite ao repetidor.

O repetidor da segunda coluna é então invocado e repete a fatia (array.length / columnCount, array.length) que produz a segunda metade da matriz na coluna dois.

 
{{Feature.featurename}}
{{Feature.featurename}}
// called to format two columns state.DivideBy2 = function(nValue) { return Math.ceil(nValue /2); };

Espero que isso ajude a ver a solução de outra maneira. (PS este é o meu primeiro post aqui! :-))

Eu corrijo sem.

 
Content here...

e css

 .left { float: left; } 

Aqui está uma maneira fácil de fazer isso. É mais manual e acaba com a marcação desordenada. Eu não recomendo isso, mas há situações em que isso pode ser útil.

Aqui está um link de violino http://jsfiddle.net/m0nk3y/9wcbpydq/

HTML:

 
{{ person.name }}
{{ person.name }}
{{ person.name }}

JS:

 var app = angular.module('myApp', []); app.controller('myController', function($scope) { $scope.Math = Math; $scope.data = [ {"name":"Person A"}, ... ]; }); 

Esta configuração requer que usemos alguma Matemática na marcação: /, então você precisará injetar Matemática adicionando esta linha: $scope.Math = Math;

Todas essas respostas parecem maciçamente projetadas.

De longe, o método mais simples seria configurar os divs de input em um bootstrap de coluna col-md-4, então o bootstrap irá formatá-lo automaticamente em 3 colunas devido à natureza de 12 colunas do bootstrap:

 
 
  • {{item}}

Um truque simples com CSS “clearfix” recomendado pelo Bootstrap:

 
{{value}}

Baseando-se na resposta muito boa do m59. Achei que as inputs do modelo ficariam borradas se elas mudassem, então você só poderia alterar um caractere por vez. Este é um novo para listas de objects para qualquer um que precise dele:

EDIT Atualizado para lidar com vários filtros em uma página

 app.filter('partition', function() { var cache = {}; // holds old arrays for difference repeat scopes var filter = function(newArr, size, scope) { var i, oldLength = 0, newLength = 0, arr = [], id = scope.$id, currentArr = cache[id]; if (!newArr) return; if (currentArr) { for (i = 0; i < currentArr.length; i++) { oldLength += currentArr[i].length; } } if (newArr.length == oldLength) { return currentArr; // so we keep the old object and prevent rebuild (it blurs inputs) } else { for (i = 0; i < newArr.length; i += size) { arr.push(newArr.slice(i, i + size)); } cache[id] = arr; return arr; } }; return filter; }); 

E isso seria o uso:

 
{{ $index }}

Eu sou novo em bootstrap e angularjs, mas isso também poderia fazer Array por 4 itens como um grupo, o resultado será quase como 3 colunas. Este truque usa o princípio da linha de quebra de bootstrap.

 
{{item.XX}}

Lodash tem um método de chunk embutido agora que eu pessoalmente uso: https://lodash.com/docs#chunk

Com base nisso, o código do controlador pode se parecer com o seguinte:

 $scope.groupedUsers = _.chunk( $scope.users, 3 ) 

Visualizar código:

 
{{item}}

Outra maneira é definir width:33.33%; float:left width:33.33%; float:left para um wrapper div assim:

 
{{$index}}

Eu me encontrei em um caso semelhante, querendo gerar grupos de exibição de 3 colunas cada. No entanto, embora eu estivesse usando o bootstrap, eu estava tentando separar esses grupos em divs pai diferentes. Eu também queria fazer algo genericamente útil.

Eu me aproximei com 2 ng-repeat como abaixo:

 
... some content ...

Isso facilita muito a alteração para um número diferente de colunas e a separação em vários divs principais.

Isso responde a pergunta original, que é como obter 1,2,3 em uma coluna. – perguntou por kuppu 08 de fevereiro ’14 às 13:47

código angularjs:

 function GetStaffForFloor(floor) { var promiseGet = Directory_Service.getAllStaff(floor); promiseGet.then(function (pl) { $scope.staffList = chunk(pl.data, 3); //pl.data; // }, function (errorOD) { $log.error('Errored while getting staff list.', errorOD); }); } function chunk(array, columns) { var numberOfRows = Math.ceil(array.length / columns); //puts 1, 2, 3 into column var newRow = []; //array is row-based. for (var i = 0; i < array.length; i++) { var columnData = new Array(columns); if (i == numberOfRows) break; for (j = 0; j < columns; j++) { columnData[j] = array[i + numberOfRows * j]; } newRow.push(columnData); } return newRow; ////this works but 1, 2, 3 is in row //var newRow = []; //for (var i = 0; i < array.length; i += columns) { // newRow.push(array.slice(i, i + columns)); //push effectively does the pivot. array is row-based. //} //return newRow; }; 

Ver código (nota: usando bootstrap 3):

 
{{item.FullName.length > 0 ? item.FullName + ": Rm " + item.RoomNumber : ""}}