แนวทางที่น่าเชื่อถือที่สุดและถูกต้องทางเทคนิคคือการแปลงข้อมูลในคอนโทรลเลอร์ นี่คือฟังก์ชั่นและการใช้งานที่เรียบง่าย
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 ตระหนักว่ามีการวนรอบการย่อยที่ไม่สิ้นสุดเกิดขึ้นและปิดตัวลง เนื่องจากอาร์เรย์ / อ็อบเจ็กต์ที่ซ้อนกันใหม่ไม่ได้ถูกติดตามโดย Angular ก่อนหน้านี้จึงเห็นค่าที่ส่งคืนแตกต่างจากก่อนหน้านี้เสมอ ในการแก้ไขตัวกรอง "ไม่เสถียร" เหล่านี้คุณต้องรวมตัวกรองไว้ในmemoize
ฟังก์ชัน lodash
มีmemoize
ฟังก์ชันและเวอร์ชันล่าสุดของ lodash ยังมีchunk
ฟังก์ชันดังนั้นเราจึงสามารถสร้างตัวกรองนี้ได้อย่างง่ายดายโดยใช้npm
โมดูลและการคอมไพล์สคริปต์ด้วยbrowserify
or 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>