角ng-repeat,每3或4个cols添加引导行

时间:2022-12-08 02:59:50

I'm looking for the right pattern to inject a bootstrap row class every each 3 columns. I need this because cols doesn't have a fixed hight (and I don't want to fix one), so it breaks my design !

我正在寻找合适的模式来为每3列注入引导行类。我需要这个,因为cols没有固定的高度(我也不想修复),所以它破坏了我的设计!

Here is my code :

这是我的代码:

<div ng-repeat="product in products">
    <div ng-if="$index % 3 == 0" class="row">
        <div class="col-sm-4" >
            ...
        </div>
    </div>
</div>

But it does only display one product in each row. What I want as final result is :

但是它只在每一行显示一个产品。我想要的最终结果是:

<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>

Can I achieve this with only ng-repeat pattern (without directive or controller) ? The docs introduce ng-repeat-start and ng-repeat-end but I can't figure out how to use it is this use case ! I feel like this is something we often use in bootstrap templating ! ? Thanks

我是否可以只使用ng-repeat模式(没有指令或控制器)实现这一点?这些文档引入了ng-repeat-start和ng-repeat-end,但我不知道如何使用它是这个用例!我觉得这是我们经常用在bootstrap模板!吗?谢谢

17 个解决方案

#1


149  

The top voted answer, while effective, is not what I would consider to be the angular way, nor is it using bootstrap's own classes that are meant to deal with this situation. As @claies mentioned, the .clearfix class is meant for situations such as these. In my opinion, the cleanest implementation is as follows:

上面投票的答案虽然有效,但不是我认为的角度方式,也不是使用bootstrap自己的类来处理这种情况。正如@claies所提到的,.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>

This structure avoids messy indexing of the products array, allows for clean dot notation, and makes use of the clearfix class for its intended purpose.

这种结构避免了产品数组的混乱索引,允许使用干净的点表示法,并将clearfix类用于其预期目的。

#2


145  

I know it's a bit late but it still might help someone. I did it like this:

我知道有点晚了,但还是可以帮助别人的。我是这样做的:

<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

jsfiddle

#3


23  

Okay, this solution is far simpler than the ones already here, and allows different column widths for different device widths.

好的,这个解决方案比已经在这里的要简单得多,并且允许不同的设备宽度的不同的列宽度。

<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>

Note that the % 6 part is supposed to equal the number of resulting columns. So if on the column element you have the class col-lg-2 there will be 6 columns, so use ... % 6.

注意,% 6部分应该等于结果列的数量。因此,如果在列元素上有coll -lg-2类,将有6列,所以使用…% 6。

This technique (excluding the ng-if) is actually documented here: Bootstrap docs

这种技术(不包括ng-if)实际上在这里被记录:引导文档

#4


17  

While what you want to accomplish may be useful, there is another option which I believe you might be overlooking that is much more simple.

虽然你想要完成的事情可能是有用的,但我相信你可能忽略了另一种选择,那就简单多了。

You are correct, the Bootstrap tables act strangely when you have columns which are not fixed height. However, there is a bootstrap class created to combat this issue and perform responsive resets.

你是对的,当你有不固定高度的列时,引导表的行为很奇怪。但是,创建了一个bootstrap类来解决这个问题并执行响应性重置。

simply create an empty <div class="clearfix"></div> before the start of each new row to allow the floats to reset and the columns to return to their correct positions.

只需在每个新行开始之前创建一个空的

,以允许浮动重置和列返回它们的正确位置。

here is a bootply.

这是bootp。

#5


16  

Thanks for your suggestions, you got me on the right way !

谢谢你的建议,你让我走对了路!

Let's go for a complete explanation :

让我们来做一个完整的解释:

  • By default AngularJS http get query returns an object

    默认情况下,AngularJS http get查询返回一个对象

  • So if you want to use @Ariel Array.prototype.chunk function you have first to transform object into an array.

    如果你想使用@Ariel Array.prototype的话。chunk函数,首先将对象转换为数组。

  • And then to use the chunk function IN YOUR CONTROLLER otherwise if used directly into ng-repeat, it will brings you to an infdig error. The final controller looks :

    然后在控制器中使用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);
    });
    

And HTML becomes :

和HTML就变成:

<div class="row" ng-repeat="productrow in products">

    <div class="col-sm-4" ng-repeat="product in productrow">

On the other side, I decided to directly return an array [] instead of an object {} from my JSON file. This way, controller becomes (please note specific syntax isArray:true) :

另一方面,我决定从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 stay the same as above.

HTML与上面一样。

OPTIMIZATION

优化

Last question in suspense is : how to make it 100% AngularJS without extending javascript array with chunk function ... if some people are interested in showing us if ng-repeat-start and ng-repeat-end are the way to go ... I'm curious ;)

悬疑的最后一个问题是:如何在不使用chunk函数扩展javascript数组的情况下,使其100%为AngularJS…如果有人有兴趣向我们展示,ng-repeat-start和ng-repeat-end是否可行……我很好奇。

ANDREW'S SOLUTION

安德鲁的解决方案

Thanks to @Andrew, we now know adding a bootstrap clearfix class every three (or whatever number) element corrects display problem from differents block's height.

感谢@Andrew,我们现在知道每增加一个引导clearfix类3(或任何数字)元素就可以从不同块的高度纠正显示问题。

So HTML becomes :

所以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}}

And your controller stays quite soft with removed chunck function :

您的控制器保持相当软与删除的块功能:

// 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;
        });

#6


7  

Based on Alpar solution, using only templates with anidated ng-repeat. Works with both full and partially empty rows:

基于Alpar解决方案,只使用带有标记的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

JSFiddle

#7


6  

You can do it without a directive but i'm not sure it's the best way. To do this you must create array of array from the data you want to display in the table, and after that use 2 ng-repeat to iterate through the array.

你可以在没有指示的情况下做,但我不确定这是最好的方法。为此,必须从要显示在表中的数据创建数组,然后使用2 ng-repeat遍历数组。

to create the array for display use this function like that products.chunk(3)

要创建要显示的数组,请使用类似product .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)];
        })
    );
}

and then do something like that using 2 ng-repeat

然后用2个ng-repeat来做类似的事情

<div class="row" ng-repeat="row in products.chunk(3)">
  <div class="col-sm4" ng-repeat="item in row">
    {{item}}
  </div>
</div>

#8


5  

I've just made a solution of it working only in template. The solution is

我刚刚做了一个只在模板中工作的解决方案。解决方案是

    <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 is using data twice, one is for an outside loop. Extra span tags will remain, but it depends on how you trade off.

点是使用数据两次,一个是外部循环。额外的跨度标记将保留下来,但这取决于您如何权衡。

If it's a 3 column layout, it's going to be like

如果它是一个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>

Honestly I wanted

说实话我想

$index<Math.ceil(products.length/3)

Although it didn't work.

虽然它没有工作。

#9


5  

Just another little improvement about @Duncan answer and the others answers based on clearfix element. If you want to make the content clickable you will need a z-index > 0 on it or clearfix will overlap the content and handle the click.

关于@Duncan的回答以及其他基于clearfix元素的回答,还有一个小小的改进。如果你想让内容可点击,你需要一个z索引>,否则clearfix会覆盖内容并处理点击。

This is the example not working (you can't see the cursor pointer and clicking will do nothing):

这是不工作的例子(你看不到光标指针,点击什么都不做):

<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>

While this is the fixed one:

这是固定的:

<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>

I've added z-index: 1 to have the content raise over the clearfix and I've removed the container div using instead ng-repeat-start and ng-repeat-end (available from AngularJS 1.2) because it made z-index not working.

我添加了z-index: 1以使内容在clearfix上增加,并且我已经删除了容器div,使用了ng-repeat-start和ng-repeat-end(来自AngularJS 1.2),因为它使z索引不工作。

Hope this helps!

希望这可以帮助!

Update

Plunker: http://plnkr.co/edit/4w5wZj

砰砰作响:http://plnkr.co/edit/4w5wZj

#10


4  

i solved this using ng-class

我用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>

#11


2  

The best way to apply a class is to use ng-class.It can be used to apply classes based on some condition.

应用类的最佳方法是使用ng-class。它可以根据某些条件应用类。

<div ng-repeat="product in products">
   <div ng-class="getRowClass($index)">
       <div class="col-sm-4" >
           <!-- your code -->
       </div>
   </div>

and then in your controller

然后在控制器中

$scope.getRowClass = function(index){
    if(index%3 == 0){
     return "row";
    }
}

#12


1  

Little bit modification in @alpar 's solution

@alpar的解决方案中有一点修改

<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

jsfiddle

#13


1  

After combining many answers and suggestion here, this is my final answer, which works well with flex, which allows us to make columns with equal height, it also checks the last index, and you don't need to repeat the inner HTML. It doesn't use clearfix:

在这里结合了许多答案和建议之后,这是我的最终答案,它可以很好地与flex一起使用,它允许我们创建具有相同高度的列,它还检查最后的索引,您不需要重复内部的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>

It will output something like this:

它将输出如下内容:

<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>

#14


0  

This worked for me, no splicing or anything required:

这对我来说是可行的,没有剪接或任何要求:

HTML

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

JavaScript

var columnsPerRow = 4;
$scope.rows = function() {
  return new Array(columnsPerRow);
};
$scope.indexInRange = function(columnIndex,rowIndex) {
  return columnIndex >= (rowIndex * columnsPerRow) && columnIndex < (rowIndex * columnsPerRow) + columnsPerRow;
};

#15


0  

Born Solutions its best one, just need a bit tweek to feet the needs, i had different responsive solutions and changed a bit

天生的解决方案是最好的,只是需要一点时间来满足需求,我有不同的响应解决方案,并且改变了一点。

<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>

#16


0  

Try this Example

试试这个例子

<!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="https://maxcdn.bootstrapcdn.com/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>

#17


-1  

Building on Alpar's answer, here's a more generalised way to split a single list of items into multiple containers (rows, columns, buckets, whatever):

基于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> 

for a list of 10 items, generates:

对于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> 

The number of containers can be quickly coded into a controller function:

容器的数量可以快速编码成一个控制器函数:

JS (ES6)

JS(ES6)

$scope.rowList = function(rows) {
  return Array(rows).fill().map((x,i)=>i);
}
$scope.rows = 2;

HTML

HTML

<div class="row" ng-repeat="row in rowList(rows)">
  <div ng-repeat="item in $ctrl.items" ng-if="$index % rows == row">
    ...

This approach avoids duplicating the item markup (<span>{{item.name}}</span> in this case) in the source template - not a huge win for a simple span, but for a more complex DOM structure (which I had) this helps keep the template DRY.

这种方法避免了在源模板中复制项目标记(在本例中为{{item.name}})——对于简单的跨度来说,这不是一个巨大的胜利,但对于更复杂的DOM结构(我有),这有助于保持模板干燥。

#1


149  

The top voted answer, while effective, is not what I would consider to be the angular way, nor is it using bootstrap's own classes that are meant to deal with this situation. As @claies mentioned, the .clearfix class is meant for situations such as these. In my opinion, the cleanest implementation is as follows:

上面投票的答案虽然有效,但不是我认为的角度方式,也不是使用bootstrap自己的类来处理这种情况。正如@claies所提到的,.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>

This structure avoids messy indexing of the products array, allows for clean dot notation, and makes use of the clearfix class for its intended purpose.

这种结构避免了产品数组的混乱索引,允许使用干净的点表示法,并将clearfix类用于其预期目的。

#2


145  

I know it's a bit late but it still might help someone. I did it like this:

我知道有点晚了,但还是可以帮助别人的。我是这样做的:

<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

jsfiddle

#3


23  

Okay, this solution is far simpler than the ones already here, and allows different column widths for different device widths.

好的,这个解决方案比已经在这里的要简单得多,并且允许不同的设备宽度的不同的列宽度。

<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>

Note that the % 6 part is supposed to equal the number of resulting columns. So if on the column element you have the class col-lg-2 there will be 6 columns, so use ... % 6.

注意,% 6部分应该等于结果列的数量。因此,如果在列元素上有coll -lg-2类,将有6列,所以使用…% 6。

This technique (excluding the ng-if) is actually documented here: Bootstrap docs

这种技术(不包括ng-if)实际上在这里被记录:引导文档

#4


17  

While what you want to accomplish may be useful, there is another option which I believe you might be overlooking that is much more simple.

虽然你想要完成的事情可能是有用的,但我相信你可能忽略了另一种选择,那就简单多了。

You are correct, the Bootstrap tables act strangely when you have columns which are not fixed height. However, there is a bootstrap class created to combat this issue and perform responsive resets.

你是对的,当你有不固定高度的列时,引导表的行为很奇怪。但是,创建了一个bootstrap类来解决这个问题并执行响应性重置。

simply create an empty <div class="clearfix"></div> before the start of each new row to allow the floats to reset and the columns to return to their correct positions.

只需在每个新行开始之前创建一个空的

,以允许浮动重置和列返回它们的正确位置。

here is a bootply.

这是bootp。

#5


16  

Thanks for your suggestions, you got me on the right way !

谢谢你的建议,你让我走对了路!

Let's go for a complete explanation :

让我们来做一个完整的解释:

  • By default AngularJS http get query returns an object

    默认情况下,AngularJS http get查询返回一个对象

  • So if you want to use @Ariel Array.prototype.chunk function you have first to transform object into an array.

    如果你想使用@Ariel Array.prototype的话。chunk函数,首先将对象转换为数组。

  • And then to use the chunk function IN YOUR CONTROLLER otherwise if used directly into ng-repeat, it will brings you to an infdig error. The final controller looks :

    然后在控制器中使用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);
    });
    

And HTML becomes :

和HTML就变成:

<div class="row" ng-repeat="productrow in products">

    <div class="col-sm-4" ng-repeat="product in productrow">

On the other side, I decided to directly return an array [] instead of an object {} from my JSON file. This way, controller becomes (please note specific syntax isArray:true) :

另一方面,我决定从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 stay the same as above.

HTML与上面一样。

OPTIMIZATION

优化

Last question in suspense is : how to make it 100% AngularJS without extending javascript array with chunk function ... if some people are interested in showing us if ng-repeat-start and ng-repeat-end are the way to go ... I'm curious ;)

悬疑的最后一个问题是:如何在不使用chunk函数扩展javascript数组的情况下,使其100%为AngularJS…如果有人有兴趣向我们展示,ng-repeat-start和ng-repeat-end是否可行……我很好奇。

ANDREW'S SOLUTION

安德鲁的解决方案

Thanks to @Andrew, we now know adding a bootstrap clearfix class every three (or whatever number) element corrects display problem from differents block's height.

感谢@Andrew,我们现在知道每增加一个引导clearfix类3(或任何数字)元素就可以从不同块的高度纠正显示问题。

So HTML becomes :

所以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}}

And your controller stays quite soft with removed chunck function :

您的控制器保持相当软与删除的块功能:

// 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;
        });

#6


7  

Based on Alpar solution, using only templates with anidated ng-repeat. Works with both full and partially empty rows:

基于Alpar解决方案,只使用带有标记的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

JSFiddle

#7


6  

You can do it without a directive but i'm not sure it's the best way. To do this you must create array of array from the data you want to display in the table, and after that use 2 ng-repeat to iterate through the array.

你可以在没有指示的情况下做,但我不确定这是最好的方法。为此,必须从要显示在表中的数据创建数组,然后使用2 ng-repeat遍历数组。

to create the array for display use this function like that products.chunk(3)

要创建要显示的数组,请使用类似product .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)];
        })
    );
}

and then do something like that using 2 ng-repeat

然后用2个ng-repeat来做类似的事情

<div class="row" ng-repeat="row in products.chunk(3)">
  <div class="col-sm4" ng-repeat="item in row">
    {{item}}
  </div>
</div>

#8


5  

I've just made a solution of it working only in template. The solution is

我刚刚做了一个只在模板中工作的解决方案。解决方案是

    <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 is using data twice, one is for an outside loop. Extra span tags will remain, but it depends on how you trade off.

点是使用数据两次,一个是外部循环。额外的跨度标记将保留下来,但这取决于您如何权衡。

If it's a 3 column layout, it's going to be like

如果它是一个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>

Honestly I wanted

说实话我想

$index<Math.ceil(products.length/3)

Although it didn't work.

虽然它没有工作。

#9


5  

Just another little improvement about @Duncan answer and the others answers based on clearfix element. If you want to make the content clickable you will need a z-index > 0 on it or clearfix will overlap the content and handle the click.

关于@Duncan的回答以及其他基于clearfix元素的回答,还有一个小小的改进。如果你想让内容可点击,你需要一个z索引>,否则clearfix会覆盖内容并处理点击。

This is the example not working (you can't see the cursor pointer and clicking will do nothing):

这是不工作的例子(你看不到光标指针,点击什么都不做):

<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>

While this is the fixed one:

这是固定的:

<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>

I've added z-index: 1 to have the content raise over the clearfix and I've removed the container div using instead ng-repeat-start and ng-repeat-end (available from AngularJS 1.2) because it made z-index not working.

我添加了z-index: 1以使内容在clearfix上增加,并且我已经删除了容器div,使用了ng-repeat-start和ng-repeat-end(来自AngularJS 1.2),因为它使z索引不工作。

Hope this helps!

希望这可以帮助!

Update

Plunker: http://plnkr.co/edit/4w5wZj

砰砰作响:http://plnkr.co/edit/4w5wZj

#10


4  

i solved this using ng-class

我用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>

#11


2  

The best way to apply a class is to use ng-class.It can be used to apply classes based on some condition.

应用类的最佳方法是使用ng-class。它可以根据某些条件应用类。

<div ng-repeat="product in products">
   <div ng-class="getRowClass($index)">
       <div class="col-sm-4" >
           <!-- your code -->
       </div>
   </div>

and then in your controller

然后在控制器中

$scope.getRowClass = function(index){
    if(index%3 == 0){
     return "row";
    }
}

#12


1  

Little bit modification in @alpar 's solution

@alpar的解决方案中有一点修改

<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

jsfiddle

#13


1  

After combining many answers and suggestion here, this is my final answer, which works well with flex, which allows us to make columns with equal height, it also checks the last index, and you don't need to repeat the inner HTML. It doesn't use clearfix:

在这里结合了许多答案和建议之后,这是我的最终答案,它可以很好地与flex一起使用,它允许我们创建具有相同高度的列,它还检查最后的索引,您不需要重复内部的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>

It will output something like this:

它将输出如下内容:

<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>

#14


0  

This worked for me, no splicing or anything required:

这对我来说是可行的,没有剪接或任何要求:

HTML

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

JavaScript

var columnsPerRow = 4;
$scope.rows = function() {
  return new Array(columnsPerRow);
};
$scope.indexInRange = function(columnIndex,rowIndex) {
  return columnIndex >= (rowIndex * columnsPerRow) && columnIndex < (rowIndex * columnsPerRow) + columnsPerRow;
};

#15


0  

Born Solutions its best one, just need a bit tweek to feet the needs, i had different responsive solutions and changed a bit

天生的解决方案是最好的,只是需要一点时间来满足需求,我有不同的响应解决方案,并且改变了一点。

<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>

#16


0  

Try this Example

试试这个例子

<!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="https://maxcdn.bootstrapcdn.com/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>

#17


-1  

Building on Alpar's answer, here's a more generalised way to split a single list of items into multiple containers (rows, columns, buckets, whatever):

基于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> 

for a list of 10 items, generates:

对于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> 

The number of containers can be quickly coded into a controller function:

容器的数量可以快速编码成一个控制器函数:

JS (ES6)

JS(ES6)

$scope.rowList = function(rows) {
  return Array(rows).fill().map((x,i)=>i);
}
$scope.rows = 2;

HTML

HTML

<div class="row" ng-repeat="row in rowList(rows)">
  <div ng-repeat="item in $ctrl.items" ng-if="$index % rows == row">
    ...

This approach avoids duplicating the item markup (<span>{{item.name}}</span> in this case) in the source template - not a huge win for a simple span, but for a more complex DOM structure (which I had) this helps keep the template DRY.

这种方法避免了在源模板中复制项目标记(在本例中为{{item.name}})——对于简单的跨度来说,这不是一个巨大的胜利,但对于更复杂的DOM结构(我有),这有助于保持模板干燥。