[英]Manipulate DOM from directive after data is bound
我的目标是创建一个指令,将一组不同的高度div排列成一个模式,消除它们之间的空白。 就像Pinterest将divs镶嵌成马赛克一样:
我的方法是:
创建一个指令,将一组div包装到tessellate。
<tessellate columns="6"> <div ng-repeat="item in items" class="thumbnail"> {{item.name}} </div> </tessellate>
使用指令模板首先设置列。 (tessellateTemplate.html)
<div class="container"> <div class="row"> <div class="col-sm-{{12/columns}}" ng-repeat="i in numberToArray(columns) track by $index"></div> </div> </div>
使用该指令在数据绑定到 div 后抓取div ,并逐个将它们添加到具有最短高度的列中。
app.directive('tessellate', function () { return { restrict: 'E', scope: { columns: '=' }, controller: ['$scope', function ($scope) { // Ensure number of columns is divisible by 12. if (isNaN($scope.columns) || 12 % $scope.columns != 0) { $scope.columns = 6; } $scope.numberToArray = function (num) { return new Array(num); }; }], // Get child divs and add to template here. // Should I use compile or link?? templateUrl: "/app/directives/templates/tessellateTemplate.html" }; });
看起来很简单吧? 我一直遇到的问题是我无法弄清楚如何在绑定数据后获取div。 这很重要,因为需要div的实际高度来决定它应该进入哪一列。
在数据绑定后,有没有办法在指令中操作DOM?
要回答我自己的问题,我能解决这个问题的唯一方法是使用$ timeout。 我不是它的粉丝,但它有效。 如果有人有更好的方法,请发一个答案。 :)
我修改了我的指令模板(tessellateTemplate.html)来转换div:
<div>
<div class="container">
<div class="row">
<div class="col-sm-{{12/columns}}" ng-repeat="i in numberToArray(columns) track by $index"></div>
</div>
</div>
<div ng-transclude></div>
</div>
然后我修改了我的指令以转换transclude: true
并且还在$ timeout中进行细分(请不要嘲笑我的链式方法调用,已经有一段时间了,因为我必须使用JQuery:P):
app.directive('tessellate', function () {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
columns: '='
},
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
// Ensure number of columns is divisible by 12.
if (isNaN($scope.columns) || 12 % $scope.columns != 0) {
$scope.columns = 6;
}
$scope.numberToArray = function (num) {
return new Array(num);
};
$scope.getShortestColumn = function () {
var cols = $element.children().first().children().first().children();
var shortCol = null;
angular.forEach(cols, function (col) {
col = angular.element(col);
if (shortCol == null || col.height() < shortCol.height()) {
shortCol = col;
}
});
return shortCol;
};
$timeout(function () {
var divs = $element.children().first().next().children();
for (var i = 0; i < divs.length; i++) {
$scope.getShortestColumn().append(divs[i]);
}
}, 0);
}],
templateUrl: "/app/directives/templates/tessellateTemplate.html"
};
});
用法保持不变:
<tessellate columns="6">
<div ng-repeat="item in items">
{{item.name}}
</div>
</tessellate>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.