Angular ng-repeat每3或4列添加bootstrap行
我正在寻找正确的模式,每3列注入一个引导行类。 我需要这个,因为cols没有固定的高度(我不想修复),所以它打破了我的devise!
这是我的代码:
<div ng-repeat="product in products"> <div ng-if="$index % 3 == 0" class="row"> <div class="col-sm-4" > ... </div> </div> </div>
但它只在每一行显示一个产品。 我想要的最终结果是:
<div class="row"> <div class="col-sm4"> ... </div> <div class="col-sm4"> ... </div> <div class="col-sm4"> ... </div> </div> <div class="row"> <div class="col-sm4"> ... </div> <div class="col-sm4"> ... </div> <div class="col-sm4"> ... </div> </div>
我可以用ng-repeat模式(没有指令或控制器)来实现吗? 文档介绍了ng-repeat-start和ng-repeat-end,但我不知道如何使用它是这个用例! 我觉得这是我们经常在bootstrap模板中使用的东西! ? 谢谢
我知道这有点晚,但仍然可以帮助某人。 我是这样做的:
<div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row"> <div class="col-xs-4">{{products[$index]}}</div> <div class="col-xs-4" ng-if="products.length > ($index + 1)">{{products[$index + 1]}}</div> <div class="col-xs-4" ng-if="products.length > ($index + 2)">{{products[$index + 2]}}</div> </div>
的jsfiddle
最高投票的答案虽然有效,但并不是我认为是有效的方式,也不是用引导程序自己的类来处理这种情况。 正如@clauses所提到的, .clearfix
类是针对这些情况的。 在我看来,最简洁的实施如下:
<div class="row"> <div ng-repeat="product in products"> <div class="clearfix" ng-if="$index % 3 == 0"></div> <div class="col-sm-4"> <h2>{{product.title}}</h2> </div> </div> </div>
这种结构避免了产品数组的凌乱索引,允许使用干净的点符号,并使用clearfix类来达到预期的目的。
好的,这个解决scheme比现在的解决scheme简单得多,并且允许不同的列宽适用于不同的器件宽度。
<div class="row"> <div ng-repeat="image in images"> <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2"> ... your content here ... </div> <div class="clearfix visible-lg" ng-if="($index + 1) % 6 == 0"></div> <div class="clearfix visible-md" ng-if="($index + 1) % 4 == 0"></div> <div class="clearfix visible-sm" ng-if="($index + 1) % 3 == 0"></div> <div class="clearfix visible-xs" ng-if="($index + 1) % 2 == 0"></div> </div> </div>
请注意, % 6
部分应该等于结果列的数量。 所以,如果在列元素上有类col-lg-2
那么将会有6列,所以使用... % 6
。
这种技术(不包括ng-if
)实际上logging在这里: Bootstrap文档
虽然你想完成什么可能是有用的,但我相信你可能会忽略的另一个select是简单得多。
你是正确的,Bootstrap表的行为奇怪,当你有不固定的高度的列。 但是,有一个引导类创build来解决这个问题,并执行响应的重置 。
只需在每个新行开始之前创build一个空的<div class="clearfix"></div>
以允许浮动<div class="clearfix"></div>
重置,并且列可以返回到正确的位置。
这里是一个bootply 。
感谢您的build议,让我走上了正确的道路!
我们来做一个完整的解释:
-
默认情况下,AngularJS http get查询返回一个对象
-
所以如果你想使用@Ariel Array.prototype.chunk函数,你首先要把对象转换成一个数组。
-
然后在你的控制器中使用块函数,否则如果直接使用ng-repeat,它会带来一个infdig错误 。 最后的控制者看起来:
// Initialize products to empty list $scope.products = []; // Load products from config file $resource("/json/shoppinglist.json").get(function (data_object) { // Transform object into array var data_array =[]; for( var i in data_object ) { if (typeof data_object[i] === 'object' && data_object[i].hasOwnProperty("name")){ data_array.push(data_object[i]); } } // Chunk Array and apply scope $scope.products = data_array.chunk(3); });
而HTML变成:
<div class="row" ng-repeat="productrow in products"> <div class="col-sm-4" ng-repeat="product in productrow">
另一方面,我决定直接从我的JSON文件中返回一个数组[]而不是一个对象{}。 这样,控制器就变成了(请注意特定的语法isArray:true ):
// Initialize products to empty list $scope.products = []; // Load products from config file $resource("/json/shoppinglist.json").query({method:'GET', isArray:true}, function (data_array) { $scope.products = data_array.chunk(3); });
HTML保持与上述相同。
优化
悬而未决的最后一个问题是:如何使它成为100%的AngularJS,而不用扩展JavaScript数组和块函数…如果有人有兴趣向我们展示如果ng-repeat-start和ng-repeat-end是要走的路。 。 我很好奇 ;)
安德鲁的解决scheme
感谢@Andrew,现在我们知道每三个(或任何数字)元素都会增加一个引导程序clearfix类来纠正来自不同块高度的显示问题。
所以HTML变成:
<div class="row"> <div ng-repeat="product in products"> <div ng-if="$index % 3 == 0" class="clearfix"></div> <div class="col-sm-4"> My product descrition with {{product.property}}
而你的控制器保持非常柔和, 删除chunckfunction:
// Initialize products to empty list $scope.products = []; // Load products from config file $resource("/json/shoppinglist.json").query({method:'GET', isArray:true}, function (data_array) { //$scope.products = data_array.chunk(3); $scope.products = data_array; });
基于Alpar解决scheme,仅使用具有ng-repeat的模板。 适用于全部和部分空行:
<div data-ng-app="" data-ng-init="products='soda','beer','water','milk','wine']" class="container"> <div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row"> <div class="col-xs-4" ng-repeat="product in products.slice($index, ($index+3 > products.length ? products.length : $index+3))"> {{product}}</div> </div> </div>
的jsfiddle
你可以没有指令,但我不知道这是最好的方法。 要做到这一点,你必须从你想要在表中显示的数据创build数组数组,然后使用2 ng-repeat来遍历数组。
创build用于显示的数组,就像那个products.chunk(3)
Array.prototype.chunk = function(chunkSize) { var array=this; return [].concat.apply([], array.map(function(elem,i) { return i%chunkSize ? [] : [array.slice(i,i+chunkSize)]; }) ); }
然后用2 ng重复做类似的事情
<div class="row" ng-repeat="row in products.chunk(3)"> <div class="col-sm4" ng-repeat="item in row"> {{item}} </div> </div>
只是关于@Duncan答案的另一个小改进,其他答案基于clearfix元素。 如果你想让内容可点击,你需要一个z-index
> 0,否则clearfix会重叠内容并处理点击。
这是这个例子不工作 (你不能看到光标指针,点击将不会执行任何操作):
<div class="row"> <div ng-repeat="product in products"> <div class="clearfix" ng-if="$index % 3 == 0"></div> <div class="col-sm-4" style="cursor: pointer" ng-click="doSomething()"> <h2>{{product.title}}</h2> </div> </div> </div>
虽然这是固定的 :
<div class="row"> <div ng-repeat-start="product in products" class="clearfix" ng-if="$index % 3 == 0"></div> <div ng-repeat-end class="col-sm-4" style="cursor: pointer; z-index: 1" ng-click="doSomething()"> <h2>{{product.title}}</h2> </div> </div>
我已经添加了z-index: 1
来增加clearfix的内容,而我已经使用ng-repeat-start
和ng-repeat-end
(可从AngularJS 1.2获得)删除了容器div,因为它使得z-index不工作。
希望这可以帮助!
更新
Plunker: http ://plnkr.co/edit/4w5wZj
我刚刚解决了它只能在模板中工作。 解决scheme是
<span ng-repeat="gettingParentIndex in products"> <div class="row" ng-if="$index<products.length/2+1"> <!-- 2 columns --> <span ng-repeat="product in products"> <div class="col-sm-6" ng-if="$index>=2*$parent.$index && $index <= 2*($parent.$index+1)-1"> <!-- 2 columns --> {{product.foo}} </div> </span> </div> </span>
Point使用两次数据,一次是外部循环。 额外的span标签将保留,但这取决于你如何折衷。
如果是3列布局,那将是这样的
<span ng-repeat="gettingParentIndex in products"> <div class="row" ng-if="$index<products.length/3+1"> <!-- 3 columns --> <span ng-repeat="product in products"> <div class="col-sm-4" ng-if="$index>=3*$parent.$index && $index <= 3*($parent.$index+1)-1"> <!-- 3 columns --> {{product.foo}} </div> </span> </div> </span>
老实说我想要
$index<Math.ceil(products.length/3)
虽然它没有工作。
我用ng-class解决了这个问题
<div ng-repeat="item in items"> <div ng-class="{ 'row': ($index + 1) % 4 == 0 }"> <div class="col-md-3"> {{item.name}} </div> </div> </div>
应用类的最好方法是使用ng-class。它可以用于基于某些条件应用类。
<div ng-repeat="product in products"> <div ng-class="getRowClass($index)"> <div class="col-sm-4" > <!-- your code --> </div> </div>
然后在你的控制器
$scope.getRowClass = function(index){ if(index%3 == 0){ return "row"; } }
在@alpar的解决scheme中稍作修改
<div data-ng-app="" data-ng-init="products=['A','B','C','D','E','F', 'G','H','I','J','K','L']" class="container"> <div ng-repeat="product in products" ng-if="$index % 6 == 0" class="row"> <div class="col-xs-2" ng-repeat="idx in [0,1,2,3,4,5]"> {{products[idx+$parent.$index]}} <!-- When this HTML is Big it's useful approach --> </div> </div> </div>
的jsfiddle
在这里结合了很多的答案和build议之后,这是我的最终答案,这与flex
效果很好,它允许我们创build高度相同的列,并检查最后一个索引,而不需要重复内部HTML。 它不使用clearfix
:
<div ng-repeat="prod in productsFiltered=(products | filter:myInputFilter)" ng-if="$index % 3 == 0" class="row row-eq-height"> <div ng-repeat="i in [0, 1, 2]" ng-init="product = productsFiltered[$parent.$parent.$index + i]" ng-if="$parent.$index + i < productsFiltered.length" class="col-xs-4"> <div class="col-xs-12">{{ product.name }}</div> </div> </div>
它会输出这样的东西:
<div class="row row-eq-height"> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> </div> <div class="row row-eq-height"> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> <div class="col-xs-4"> <div class="col-xs-12"> Product Name </div> </div> </div>
这工作对我来说,没有拼接或任何要求:
HTML
<div class="row" ng-repeat="row in rows() track by $index"> <div class="col-md-3" ng-repeat="item in items" ng-if="indexInRange($index,$parent.$index)"></div> </div>
JavaScript的
var columnsPerRow = 4; $scope.rows = function() { return new Array(columnsPerRow); }; $scope.indexInRange = function(columnIndex,rowIndex) { return columnIndex >= (rowIndex * columnsPerRow) && columnIndex < (rowIndex * columnsPerRow) + columnsPerRow; };
Born Solutions是最好的解决scheme,只需要一点点的时间来满足需求,我有不同的响应解决scheme,并改变了一些
<div ng-repeat="post in posts"> <div class="vechicle-single col-lg-4 col-md-6 col-sm-12 col-xs-12"> </div> <div class="clearfix visible-lg" ng-if="($index + 1) % 3 == 0"></div> <div class="clearfix visible-md" ng-if="($index + 1) % 2 == 0"></div> <div class="clearfix visible-sm" ng-if="($index + 1) % 1 == 0"></div> <div class="clearfix visible-xs" ng-if="($index + 1) % 1 == 0"></div> </div>
试试这个例子
<!DOCTYPE html> <html> <head> <title></title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="bootstrap/3.3.7/js/bootstrap.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script> <script type="text/javascript"> var app = angular.module('myApp', []); app.controller('myCtrl', function ($scope,$filter) { $scope.products =[{ id:1, name:'aa', },{ id:2, name:'bb', },{ id:3, name:'cc', },{ id:4, name:'dd', },{ id:5, name:'ee', }]; }); </script> </head> <body ng-app="myApp"> <div ng-controller="myCtrl"> <div ng-repeat="product in products" ng-if="$index % 3 == 0" class="row"> <div class="col-xs-4">{{products[$index]}}</div> <div class="col-xs-4" ng-if="products.length > ($index + 1)">{{products[$index + 1]}}</div> <div class="col-xs-4" ng-if="products.length > ($index + 2)">{{products[$index + 2]}}</div> </div> </div> </body> </html>
基于Alpar的回答,下面是将单个项目列表拆分为多个容器(行,列,存储桶等)的更一般的方法:
<div class="row" ng-repeat="row in [0,1,2]"> <div class="col" ng-repeat="item in $ctrl.items" ng-if="$index % 3 == row"> <span>{{item.name}}</span> </div> </div>
对于10个项目的列表,生成:
<div class="row"> <div class="col"><span>Item 1</span></div> <div class="col"><span>Item 4</span></div> <div class="col"><span>Item 7</span></div> <div class="col"><span>Item 10</span></div> </div> <div class="row"> <div class="col"><span>Item 2</span></div> <div class="col"><span>Item 5</span></div> <div class="col"><span>Item 8</span></div> </div> <div class="row"> <div class="col"><span>Item 3</span></div> <div class="col"><span>Item 6</span></div> <div class="col"><span>Item 9</span></div> </div>
容器的数量可以快速编码成一个控制器function:
JS(ES6)
$scope.rowList = function(rows) { return Array(rows).fill().map((x,i)=>i); } $scope.rows = 2;
HTML
<div class="row" ng-repeat="row in rowList(rows)"> <div ng-repeat="item in $ctrl.items" ng-if="$index % rows == row"> ...
这种方法避免了在源模板中复制项目标记( <span>{{item.name}}</span>
) – 对于一个简单跨度来说不是一个巨大的胜利,而是对于一个更复杂的DOM结构有)这有助于保持模板干燥。
- AngularJS:观察高度变化的更好方法
- 自定义子指令访问父级的范围
- 我将如何使用AngularJS呈现dynamic定义列表?
- AngularJS错误:交叉原点请求仅支持协议scheme:http,data,chrome-extension,https
- 从指令到控制器传递AngularJS范围variables的最简单的方法是什么?
- Angular $ scope。$ apply vs $ timeout作为一个安全的$ apply
- checkbox未绑定到angularjs中的作用域
- ngModel。$ modelValue和ngModel。$ viewValue之间有什么区别
- 为什么浏览器在经过validation的XMLHttpRequest之后不重复使用授权标头?