我创建了一个“tessellate”指令,可以让您包装多个 div。
<tessellate columns="4">
<div class="thumbnail" ng-repeat="item in items track by item.id">
{{item.Name}}<br />
{{item.Summary}}
</div>
</tessellate>
它一次需要一个 div 并将其附加到指定列数中最短的列以创建镶嵌/马赛克效果。
在此处查看 plunkr:http://plnkr.co/edit/ur0bVCFRSz1UbRHeLjz8?p= preview
问题是当模型改变时,ng-repeat 使用 div在 DOM中出现的顺序而不是模型中的顺序来重绘元素。您可以看到项目首先正确排序,单击后将Add
第一列中的项目水平排序,然后是下一列中的项目,依此类推。
如何防止 ng-repeat 使用 DOM 顺序重绘元素?我已经尝试添加orderBy item.id
,但它没有帮助。
var app = angular.module('app', []);
app.controller('itemController', ['$scope', function ($scope) {
$scope.items = [
{ id:"1", Name:"Item1", Summary:"This is the summary of Item1" },
{ id:"2", Name:"Item2", Summary:"This is the summary of Item2. Some extra text on item two to test different heights." },
{ id:"3", Name:"Item3", Summary:"This is the summary of Item3" },
{ id:"4", Name:"Item4", Summary:"This is the summary of Item4. Some extra text on item four to test different heights." },
{ id:"5", Name:"Item5", Summary:"This is the summary of Item5. Some extra text on item five to test different heights. Some extra text on item to test different heights." },
{ id:"6", Name:"Item6", Summary:"This is the summary of Item6" },
{ id:"7", Name:"Item7", Summary:"This is the summary of Item7. Some extra text on item seven to test different heights." },
{ id:"8", Name:"Item8", Summary:"This is the summary of Item8" },
{ id:"9", Name:"Item9", Summary:"This is the summary of Item9. Some extra text on item nine to test different heights." },
{ id:"10", Name:"Item10", Summary:"This is the summary of Item10. Some extra text on item ten to test different heights." },
{ id:"11", Name:"Item11", Summary:"This is the summary of Item11" },
{ id:"12", Name:"Item12", Summary:"This is the summary of Item12. Some extra text on item to test different heights." },
{ id:"13", Name:"Item13", Summary:"This is the summary of Item13" },
{ id:"14", Name:"Item14", Summary:"This is the summary of Item14. Some extra text on item to test different heights." },
{ id:"15", Name:"Item15", Summary:"This is the summary of Item15. Some extra text on item to test different heights. Some extra text on item to test different heights." },
{ id:"16", Name:"Item16", Summary:"This is the summary of Item16" },
{ id:"17", Name:"Item17", Summary:"This is the summary of Item17. Some extra text on item to test different heights." },
{ id:"18", Name:"Item18", Summary:"This is the summary of Item18" }
];
$scope.inc = $scope.items.length;
$scope.add = function() {
$scope.inc = $scope.inc + 1;
$scope.items.push({ id: $scope.inc, Name: "New Item" + $scope.inc, Summary:"New Summary" });
};
}]);
app.directive('tessellate', [function () {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
columns: '='
},
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
$scope.numberToArray = function (num) {
return new Array(num);
};
}],
link: function (scope, elem, attrs, ctrl) {
scope.$watch(function () {
return elem.children().first().height();
}, function (height) {
if (height > 0) {
var containers = elem.children();
var transcludedDivsContainer = containers.first();
var targetColumns = containers.eq(1).children();
// Add the transcluded divs one at a time into the shortest column.
angular.forEach(transcludedDivsContainer.children(), function (div) {
var shortCol = null;
angular.forEach(targetColumns, function (col) {
col = angular.element(col);
if (shortCol === null || col.height() < shortCol.height()) {
shortCol = col;
}
});
shortCol.append(div);
});
}
}
);
},
templateUrl: "tessellateTemplate.html"
};
}]);