我正在使用angular.js和(为了参数)bootstrap。现在我需要迭代“事物”并在“行”中显示它们:
<div class="row">
<div class="span4">...</div>
<div class="span4">...</div>
<div class="span4">...</div>
</div>
<div class="row">
etc...
现在,如何用角度来关闭每一个三分之一的.row
div?我试过ui-if来自angular-ui,但即便如此也没有。
如果我要使用服务器端渲染,我会做这样的事情(JSP语法在这里,但无关紧要):
<div class="row>
<c:forEach items="${things}" var="thing" varStatus="i">
<div class="span4">
..
</div>
<%-- Here is the trick:--%>
<c:if test="${i.index % 3 == 2}">
</div><div class="row">
</c:if>
</c:forEach>
</div>
请注意,我需要在这里实际更改DOM,而不仅仅是css隐藏元素。我在.row
和.span4
div上尝试重复,但没有用。
答案 0 :(得分:19)
似乎1.2中的角度变化不仅有点变化,而且还有更好的方法。我创建了两个过滤器。我试图将它们合二为一,但却出现了摘要错误。以下是两个过滤器:
.filter("mySecondFilter", function(){
return function(input, row, numColumns){
var returnArray = [];
for(var x = row * numColumns; x < row * numColumns + numColumns; x++){
if(x < input.length){
returnArray.push(input[x]);
}
else{
returnArray.push(""); //this is used for the empty cells
}
}
return returnArray;
}
})
.filter("myFilter", function(){
return function(input, numColumns){
var filtered = [];
for(var x = 0; x < input.length; x++){
if(x % numColumns === 0){
filtered.push(filtered.length);
}
}
return filtered;
}
});
现在html看起来像这样:
<table border="1">
<tr data-ng-repeat="rows in (objects | myFilter:numColumns)">
<td data-ng-repeat="column in (objects | mySecondFilter:rows:numColumns)">{{ column.entry }}</td>
</tr>
</table>
jsFiddle :http://jsfiddle.net/W39Q2/
2013年9月20日编辑
在处理大量需要动态列的数据时,我想出了一个更好的方法。
HTML:
<table border="1">
<tr data-ng-repeat="object in (objects | myFilter:numColumns.length)">
<td data-ng-repeat="column in numColumns">{{ objects[$parent.$index * numColumns.length + $index].entry }}</td>
</tr>
</table>
使用Javascript:
$scope.objects = [ ];
for(var x = 65; x < 91; x++){
$scope.objects.push({
entry: String.fromCharCode(x)
});
}
$scope.numColumns = [];
$scope.numColumns.length = 3;
新过滤器:
.filter("myFilter", function(){
return function(input, columns){
var filtered = [];
for(var x = 0; x < input.length; x+= columns){
filtered.push(input[x]);
}
return filtered;
}
});
这使它成为动态的。要更改列,只需更改numColumns.length。在js小提琴中你可以看到我已将它连接到下拉列表。
jsFiddle :http://jsfiddle.net/j4MPK/
你的html标记看起来像这样:
<div data-ng-repeat="row in rows">
<div data-ng-repeat="col in row.col">{{col}}</div>
</div>
然后你可以在你的控制器中创建一个变量:
$scope.rows = [
{col: [ 1,2,3,4 ]},
{col: [ 5,6,7 ]},
{col: [ 9,10,11,12 ]}
];
这样,您可以拥有任意数量的列。
jsfiddle http://jsfiddle.net/rtCP3/39/
编辑我已经修改了小提琴,现在支持平面对象阵列:
jsfiddle: http://jsfiddle.net/rtCP3/41/
html现在看起来像这样:
<div class="row" data-ng-repeat="row in rows">
<div class="col" data-ng-repeat="col in cols">
{{objects[$parent.$index * numColumns + $index].entry}}
</div>
</div>
然后在控制器中我有:
$scope.objects = [
{entry: 'a'},
{entry: 'b'},
{entry: 'c'},
{entry: 'd'},
{entry: 'e'},
{entry: 'f'},
{entry: 'g'},
{entry: 'h'}
];
$scope.numColumns = 3;
$scope.rows = [];
$scope.rows.length = Math.ceil($scope.objects.length / $scope.numColumns);
$scope.cols = [];
$scope.cols.length = $scope.numColumns;
$ scope.numColumns变量用于指定每行中需要的列数。
要处理动态数组大小更改,请将监视放在数组的长度上(而不是整个数组,这将是redundent)
$scope.numColumns = 3;
$scope.rows = [];
$scope.cols = [];
$scope.$watch("objects.length", function(){
$scope.rows.length = Math.ceil($scope.objects.length / $scope.numColumns);
$scope.cols.length = $scope.numColumns;
});
jsfiddle :http://jsfiddle.net/rtCP3/45/
答案 1 :(得分:15)
为什么不使用像这样简单的东西? http://jsfiddle.net/everdimension/ECCL7/3/
<div ng-controller="MyCtrl as ctr">
<div class="row" ng-repeat="project in ctr.projects" ng-if="$index % 3 == 0">
<h4 class="col-sm-4" ng-repeat="project in ctr.projects.slice($index, $index+3)">
{{project}}
</h4>
</div>
</div>
答案 2 :(得分:3)
我推荐一条指令有几个原因:
这是一个建议的元素指令:
<row-generator row-data=objects col-count=3></row-generator>
在实现中,我使用的代码类似于服务器端示例:
myApp.directive('rowGenerator', function() {
var rowTemplate = '<div class="row">',
colTemplate = '<div class="span4">';
return {
restrict: 'E',
// use '=' for colCount instead of '@' so that we don't
// have to use attr.$observe() in the link function
scope: { rowData: '=', colCount: '='},
link: function(scope, element) {
// To save CPU time, we'll just watch the overall
// length of the rowData array for changes. You
// may need to watch more.
scope.$watch('rowData.length', function(value) {
var html = rowTemplate;
for(var i=0; i < scope.rowData.length; i++) {
html += colTemplate + scope.rowData[i].key + '</div>';
if (i % scope.colCount == scope.colCount - 1) {
html += '</div>' + rowTemplate;
}
}
html += '</div>';
// don't use replaceWith() as the $watch
// above will not work -- use html() instead
element.html(html);
})
}
}
});
数据:
$scope.things = [
{key: 'one'},
{key: 'two'},
{key: 3},
{key: 4},
{key: 'five'},
{key: 'six'},
{key: 77},
{key: 8}
];
为了提高效率,所示的指令仅查找rowData(即,thing)数组长度的变化。如果你想让指令更新视图,如果其中一个数组元素的值发生变化,你需要一个更昂贵的$ watch:
scope.$watch('rowData', function(value){ ... }, true)
最后的true
进行“浅层”脏检查(“比较对象是否相等而不是参考” - 请参阅docs。
我不喜欢这个指令 - 它需要知道rowData条目有一个名为key
的属性:
html += colTemplate + scope.rowData[i].key + '</div>';