My angular is 1.0.8-stable
My objective is to display data in rows of 3.
My html should look like
<div class="table-row">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
</div>
My pseudo code is if the $index mod 3 == 0 then I will display <div class="table-row">
.
if the $index mod 3 == 2, then I will display </div>
.
So far, I have this.
<div ng-repeat='item in my_works.items'>
<!-- if index mod 3 == 0 show <div>-->
<!-- if index mod 3 == 2 show </div>-->
</div>
Perhaps I was thinking it in the wrong way as there may be a more efficient way to do this in angularjs?
My angular is 1.0.8-stable
My objective is to display data in rows of 3.
My html should look like
<div class="table-row">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
</div>
My pseudo code is if the $index mod 3 == 0 then I will display <div class="table-row">
.
if the $index mod 3 == 2, then I will display </div>
.
So far, I have this.
<div ng-repeat='item in my_works.items'>
<!-- if index mod 3 == 0 show <div>-->
<!-- if index mod 3 == 2 show </div>-->
</div>
Perhaps I was thinking it in the wrong way as there may be a more efficient way to do this in angularjs?
Share Improve this question edited Oct 24, 2013 at 11:30 Kim Stacks asked Oct 24, 2013 at 11:06 Kim StacksKim Stacks 10.9k39 gold badges166 silver badges302 bronze badges 2-
first of all, there's
ngIf
, second of all - you're not the first person trying to show elements in rows of 3. Search SO for relevant questions :) – Benjamin Gruenbaum Commented Oct 24, 2013 at 11:13 - @BenjaminGruenbaum Thank you. But I am using the stable 1.0.8 so no ngIf for me. I have searched SO, so far no questions that have the same setup as mine. – Kim Stacks Commented Oct 24, 2013 at 11:29
3 Answers
Reset to default 3You can use (key, value) in expression
– where key and value can be any user defined identifiers, and expression is the scope expression giving the collection to enumerate.
You can try something like this
<div ng-repeat='(index, item) in my_works.items'>
<div class="table-row" ng-show="index % 3 == 0">
</div>
</div>
Reference
Since you can't use ng-if
in 1.0.8 here are two variations that solve the problem. They both wrap 3 items into a table-row div
The outer loop counts off in groups of three, so it fires once per outer table-row div
. The second approach uses a filter to control the loop range but it should have better performance. The first approach doesn't require a new filter.
Then the inner ng-repeat
loops through the 3 items within a row. It uses slice to get just the 3 array items needed for that particular row.
Here's a fiddle with both of the variations working: http://jsfiddle/f8D8q/4/
Option 1: Solution without a new filter:
<div ng-repeat='itemtmp in items|limitTo:(items.length/3)+1'>
<div class="table-row">
<span ng-repeat='item in items.slice($index*3,($index*3+3))'>
{{item.name}} - {{$index}}
</span>
</div>
</div>
Option 2: More performant solution using range filter from http://www.yearofmoo./2012/10/more-angularjs-magic-to-supercharge-your-webapp.html#more-about-loops
<div ng-repeat="n in [] | range:(items.length/3)+1">
<div class="table-row">
<span ng-repeat='item in items.slice($index*3,($index*3+3))'>
{{item.name}} - {{$index}}
</span>
</div>
</div>
and the associated range filter:
app.filter('range', function () {
return function (input, total) {
total = parseInt(total);
for (var i = 0; i < total; i++) {
input.push(i);
}
return input;
};
});
Both are tested (down to 1.0.2) and work.
- Convert your flat list of items to a list of lists of 3 items.
- Iterate over the list of lists.
<div class="table-row" ng-repeat="list in listOfLists"> <div class="item" ng-repeat="item in list"> {{ item }} </div> </div>
If you already have a list, items
, you could add a filter chunked
and replace listOfLists
with items|chunked:3
, assuming you implement chunked
something like this:
app.filter('chunked', function(){
return function(list, chunkSize){
var chunks = [];
angular.forEach(list, function(element, i){
if(i % chunkSize === 0){
currentChunk = [];
chunks.push(currentChunk);
}
currentChunk.push(element);
});
return chunks;
};
});
I think that matches what you are trying to do; here's a plunker: http://plnkr.co/edit/3h7JprbXFVwnNZErj7hl
I didn't get a chance to test with old Angular though.