Найбільш надійний і технічно правильний підхід - це перетворення даних в контролер. Ось така проста функція та використання.
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);
Тоді ваш погляд виглядатиме так:
<div class="row" ng-repeat="rows in chunkedData">
<div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>
Якщо у вас є якісь вхідні дані в межах ng-repeat
, ви, ймовірно, захочете зняти / знову приєднатися до масивів, коли дані будуть змінені або подані. Ось як це виглядатиме у форматі a $watch
, щоб дані завжди були доступні у вихідному, об'єднаному форматі:
$scope.$watch('chunkedData', function(val) {
$scope.data = [].concat.apply([], val);
}, true); // deep watch
Багато людей вважають за краще це досягти у вигляді з фільтром. Це можливо, але його слід використовувати лише для відображення! Якщо ви додасте вхідні дані у цей відфільтрований вигляд, це спричинить проблеми, які можна вирішити, але вони не є гарними або надійними .
Проблема цього фільтра полягає в тому, що він щоразу повертає нові вкладені масиви. Кутовий переглядає повернене значення з фільтра. Перший раз, коли фільтр запускається, Angular знає значення, а потім запускає його ще раз, щоб переконатися, що воно змінюється. Якщо обидва значення однакові, цикл закінчується. Якщо ні, фільтр буде спрацьовувати знову і знову, поки вони не будуть однаковими, або Angular зрозуміє, що відбувається нескінченний цикл дайвінгу і вимикається. Оскільки нові вкладені масиви / об'єкти раніше не відслідковувалися Angular, він завжди бачить повернене значення, яке відрізняється від попереднього. Щоб виправити ці "нестабільні" фільтри, ви повинні обернути фільтр у memoize
функції. lodash
має memoize
функцію, і остання версія lodash також включає chunk
функцію, тому ми можемо створити цей фільтр дуже просто за допомогоюnpm
модулі та компіляція сценарію з browserify
або webpack
.
Пам’ятайте: лише показ! Фільтр в контролері, якщо ви використовуєте входи!
Встановити lodash:
npm install lodash-node
Створіть фільтр:
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);
});
А ось зразок із цим фільтром:
<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>
Замовляйте предмети вертикально
1 4
2 5
3 6
Що стосується вертикальних стовпців (список зверху вниз), а не горизонтальних (зліва направо), точна реалізація залежить від бажаної семантики. Списки, які розподіляються нерівномірно, можуть поширюватися різними способами. Ось один із способів:
<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;
}
Однак самим прямим і просто простим способом отримання стовпців є використання стовпців CSS :
.columns {
columns: 3;
}
<div class="columns">
<div ng-repeat="item in ['a','b','c','d','e','f','g']">
{{item}}
</div>
</div>