我正在尝试使用bootstrap 3和angularjs创建一个网格。
我正在尝试创建的网格是这样,使用ng-repeat重复。
<div class="row">
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
</div>
我尝试将ng-if
与($index % 3 == 0)
一起使用来添加行,但这似乎并不正常。任何建议都会很棒!
谢谢!
编辑:这是我最终使用的代码:
<div ng-repeat="item in items">
<div ng-class="row|($index % 3 == 0)">
<ng-include class="col-sm-4" src="'views/items/item'"></ng-include>
</div>
</div>
答案 0 :(得分:71)
接受的答案是明显的解决方案,但是表示逻辑应保持在视图中而不是控制器或模型中。此外,我无法使OP的解决方案起作用。
当您有一个项目的平面列表(数组)时,有两种方法可以创建网格系统。 假设我们的项目列表是一个字母:
$scope.alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
这是一个纯粹的角度解决方案。
<div class="row" ng-repeat="letter in alphabet track by $index" ng-if="$index % 4 == 0">
<div class="col-xs-3 letter-box"
ng-repeat="i in [$index, $index + 1, $index + 2, $index + 3]"
ng-if="alphabet[i] != null">
<div>Letter {{i + 1}} is: <b> {{alphabet[i]}}</b></div>
</div>
</div>
外部循环在每4次迭代后执行并创建一行。对于外循环的每次运行,内循环迭代4次并创建列。由于内部循环运行4次,无论我们是否在数组中都有元素,ng-if
确保如果数组在内部循环完成之前结束,则不会创建无关的cols。
这是一个更简单的解决方案,但需要angular-filter库。
<div class="row" ng-repeat="letters in alphabet | chunkBy:4">
<div class="col-xs-3 letter-box" ng-repeat="letter in letters" >
<div>Letter {{$index + 1}} is: <b> {{letter}}</b></div>
</div>
</div>
外部循环创建4个字母的组,对应于我们的“行”
[['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H'], ... ]
内部循环遍历组并创建列。
注意:方法2可能需要为外循环的每次迭代评估过滤器,因此方法2可能无法很好地扩展到大型数据集。
答案 1 :(得分:21)
这是一个陈旧的答案!
当我写这篇文章时,我对Angular还有点新意。 Shivam下面有一个更好的答案我建议你改用。它使表示逻辑远离控制器,这是一件非常好的事情。
原始回答
您始终可以将要重复的列表拆分为控制器中的列表列表(每个列表中包含三个项目)。所以你列出的是:
$scope.split_items = [['item1', 'item2', 'item3'], ['item4', 'item5', 'item6']];
然后重复:
<div ng-repeat="items in split_items" class="row">
<div ng-repeat="item in items" class="col-md-4">
item
</div>
</div>
不确定是否有更好的方法。我也试过玩ng-if和ng-switch,但我永远无法让它工作。
答案 2 :(得分:9)
您可以简单地将数组块化为控制器内部N的子阵列。示例代码:
var array = ['A','B','C','D','E','F','G','H'];
var chunk = function(arr, size) {
var newArr = [];
for (var i=0; i<arr.length; i+=size) {
newArr.push(arr.slice(i, i+size));
}
return newArr;
};
$scope.array = chunk(array, 2);
现在在* .html文件中您只需ng-repeat
通过array
<div class="row" ng-repeat="chunk in array">
<div class="col-md-6" ng-repeat="item in chunk">
{{item}}
</div>
</div>
对我来说锻炼:) 祝你好运!
答案 3 :(得分:3)
有人可能会说下面的解决方案不遵循具有row
div的网格规则,但另一种解决方案是删除row
类(或在ng-repeat
之外使用它})并使用clearfix
类代替:
<div class="col-md-12">
<div ng-repeat="item in items">
<div ng-class="{'clearfix': $index%3 === 0}"></div>
<div class="col-md-4">{{item}}</div>
</div>
</div>
据我所知,这看起来与row
类几乎相同,但请评论可能存在的缺陷(除了我上面提到的那个)。
答案 4 :(得分:3)
使用 ng-repeat-start 和 ng-repeat-end
<div class="row">
<div ng-repeat-start="item in items track by $index" class="col-sm-4">
{{item}}
</div>
<div ng-repeat-end ng-if="($index+1) % 3 == 0" class="clearfix"></div>
</div>
使用 .visible - * 类
轻松适应不同的媒体查询<div class="row">
<div ng-repeat-start="item in items track by $index" class="col-lg-2 col-md-4 col-sm-6">
{{item}}
</div>
<div ng-repeat-end>
<div class="clearfix visible-lg-block" ng-if="($index+1) % 6 == 0"></div>
<div class="clearfix visible-md-block" ng-if="($index+1) % 3 == 0"></div>
<div class="clearfix visible-sm-block" ng-if="($index+1) % 2 == 0"></div>
</div>
</div>
我发现在主重复块之外有行管理逻辑,简洁明了。关注点分离: - )
答案 5 :(得分:2)
有点迟到但我使用了这个,我相信它对某些情况更好。您可以使用Angular Filter包及其ChunkBy过滤器。虽然这个程序包对于这个单一任务来说将是一个繁重的工具,但它还有其他有用的过滤器用于不同的任务。我使用的代码是这样的:
<div class="row mar-t2" ng-repeat="items in posts | chunkBy:3">
<div class="col-md-4" ng-repeat="post in items">
<img ng-src="{{post.featured_url}}" class="img-responsive" />
<a ng-click="modalPop(post.id)"><h1 class="s04-bas2">{{post.title.rendered}}</h1></a>
<div class="s04-spotbox2" ng-bind-html="post.excerpt.rendered"></div>
</div>
</div>
答案 6 :(得分:0)
我使用ngInit采用了稍微不同的方法。我不确定这是否是适当的解决方案,因为ngInit文档说明了
ngInit的唯一合适用途是用于别名ngRepeat的特殊属性,如下面的演示所示。除了这种情况,您应该使用控制器而不是ngInit来初始化作用域上的值。
我不确定这是否属于这种情况,但我想将此功能从控制器中移开,以便让模板设计人员更容易自由地按行分组。我仍然没有对这个绑定进行测试,但看到我按$ index跟踪我并不认为这应该是一个问题。
很想听到反馈。
我创建了一个名为&#34; splitrow&#34;的过滤器。这需要一个参数(每行中有多少项)
.filter('splitrow', function(){
return function (input, count){
var out = [];
if(typeof input === "object"){
for (var i=0, j=input.length; i < j; i+=count) {
out.push(input.slice(i, i+count));
}
}
return out;
}
});
在视图模板中,我按如下方式组织了引导行:
<div ng-init="rows = (items|splitrow:3)">
<div ng-repeat='row in rows' class="row">
<div ng-repeat="item in row track by $index" class="col-md-4">
{{item.property}}
</div>
</div>
</div>
我编辑了@ Shivam的Plunker来使用这种方法。它不需要外部库。
答案 7 :(得分:0)
我的解决方案与@CodeExpress非常相似。我创建了一个batch
过滤器,用于对数组中的项进行分组(名称是从Twig's counterpart filter借来的)。
为简单起见,我不处理关联数组。
angular.module('myapp.filters', [])
.filter('batch', function() {
var cacheInputs = [];
var cacheResults = [];
return function(input, size) {
var index = cacheInputs.indexOf(input);
if (index !== -1) {
return cacheResults[index];
}
var result = [];
for (i = 0; i < input.length; i += size) {
result.push(input.slice(i, i + size));
}
cacheInputs.push(input);
cacheResults.push(result);
return result;
}
})
;
可以这样使用:
<div ng-repeat="itemsRow in items|batch:3">
<div class="row">
<div ng-repeat="item in itemsRow">
<div class="col-md-4">
...
</div>
</div>
</div>
</div>
缓存过滤器结果以避免10 $digest() iterations reached. Aborting!
错误。
答案 8 :(得分:0)
@ CodeExpress的纯角度解决方案的Angular2版本。
alphabet: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
<div *ngIf='alphabet && alphabet.length'>
<div *ngFor='#letter of alphabet; #i = index' >
<div class="row" *ngIf='i % 4 == 0'>
<div class="col-md-3" *ngFor='#n of [i,i+1,i+2,i+3]'>
{{alphabet[n]}}
</div>
</div>
</div>
</div>
答案 9 :(得分:0)
这应该有效
<div ng-repeat="item in items">
<div ng-class="{row : ($index % 3 == 0)}">
...
</div>
</div>
答案 10 :(得分:0)
更新Angular9:
<div class="container-fluid" *ngFor="let item of alphabet; let index = index">
<div class="row" *ngIf="index % 4 == 0">
<div *ngFor="let i of [index, index+1, index+2, index+3]">
<div class="col-xs-3">{{alphabet[i]}}</div>
</div>
</div>
</div>