cómo dividir los datos de ng-repeat con tres columnas usando bootstrap
Estoy usando ng-repeat con mi código. Tengo 'n' número de cuadros de texto basados en ng-repeat. Quiero alinear el cuadro de texto con tres columnas.
este es mi codigo
<div class="control-group" ng-repeat="oneExt in configAddr.ext">
{{$index+1}}.
<input type="text" name="macAdr{{$index+1}}"
id="macAddress" ng-model="oneExt.newValue" value=""/>
</div>
El enfoque más fiable y técnicamente correcto es transformar los datos en el responsable del tratamiento. A continuación se muestra una función y un uso de fragmentos simples.
function chunk(arr, size) {
var newArr = [];
for (var i=0; i<arr.length; i+=size) {
newArr.push(arr.slice(i, i+size));
}
return newArr;
}
$scope.chunkedData = chunk(myData, 3);
Entonces tu vista se vería así:
<div class="row" ng-repeat="rows in chunkedData">
<div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>
Si tiene alguna entrada dentro del archivo ng-repeat
, probablemente desee separar o volver a unir las matrices a medida que los datos se modifican o se envían. Así es como se vería esto en un archivo $watch
, para que los datos siempre estén disponibles en el formato original combinado:
$scope.$watch('chunkedData', function(val) {
$scope.data = [].concat.apply([], val);
}, true); // deep watch
Mucha gente prefiere lograr esto en la vista con un filtro. Esto es posible, ¡pero solo debe usarse con fines de visualización! Si agrega entradas dentro de esta vista filtrada, causará problemas que pueden resolverse, pero que no son bonitos ni confiables .
El problema con este filtro es que devuelve nuevas matrices anidadas cada vez. Angular está observando el valor de retorno del filtro. La primera vez que se ejecuta el filtro, Angular conoce el valor y luego lo ejecuta nuevamente para asegurarse de que haya terminado de cambiar. Si ambos valores son iguales, el ciclo finaliza. De lo contrario, el filtro se activará una y otra vez hasta que sean iguales, o Angular se da cuenta de que se está produciendo un bucle de resumen infinito y se apaga. Debido a que Angular no rastreaba previamente las nuevas matrices/objetos anidados, siempre ve el valor de retorno como diferente del anterior. Para arreglar estos filtros "inestables", debe envolver el filtro en una memoize
función. lodash
tiene una memoize
función y la última versión de lodash también incluye una chunk
función, por lo que podemos crear este filtro de manera muy sencilla usando npm
módulos y compilando el script con browserify
o webpack
.
Recuerde: ¡solo visualización! ¡Filtra en el controlador si estás usando entradas!
Instalar lodash:
npm install lodash-node
Crea el 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);
});
Y aquí tienes una muestra con este filtro:
<div ng-repeat="row in ['a','b','c','d','e','f'] | chunk:3">
<div class="column" ng-repeat="item in row">
{{($parent.$index*row.length)+$index+1}}. {{item}}
</div>
</div>
Ordenar artículos verticalmente
1 4
2 5
3 6
Con respecto a las columnas verticales (lista de arriba a abajo) en lugar de horizontales (de izquierda a derecha), la implementación exacta depende de la semántica deseada. Las listas que se dividen de manera desigual se pueden distribuir de diferentes maneras. Aquí hay una manera:
<div ng-repeat="row in columns">
<div class="column" ng-repeat="item in row">
{{item}}
</div>
</div>
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;
}
Sin embargo, la forma más directa y sencilla de obtener columnas es utilizar columnas CSS :
.columns {
columns: 3;
}
<div class="columns">
<div ng-repeat="item in ['a','b','c','d','e','f','g']">
{{item}}
</div>
</div>
Una solución limpia y adaptable que no requiere manipulación de datos :
El HTML:
<div class="control-group" class="label"
ng-repeat="oneExt in configAddr.ext"
ng-class="{'new-row': startNewRow($index, columnBreak) }">
{{$index+1}}.
<input type="text" name="macAdr{{$index+1}}"
id="macAddress{{$index}}" ng-model="oneExt.newValue" />
</div>
El CSS:
.label {
float: left;
text-align: left;
}
.new-row {
clear: left;
}
El JavaScript:
$scope.columnBreak = 3; //Max number of colunms
$scope.startNewRow = function (index, count) {
return ((index) % count) === 0;
};
Esta es una solución sencilla para representar datos en filas y columnas de forma dinámica sin necesidad de manipular la matriz de datos que intenta mostrar. Además, si intenta cambiar el tamaño de la ventana del navegador, podrá ver que la cuadrícula se adapta dinámicamente al tamaño de la pantalla/div.
(También agregué un sufijo {{$index}} a su identificación ya que ng-repeat intentará crear múltiples elementos con la misma identificación si no lo hace).
Un ejemplo de trabajo similar