Kim Stacks
Kim Stacks

Reputation: 10812

how to use if statement in ng repeat using angular 1.0.8

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?

Upvotes: 2

Views: 3930

Answers (3)

KayakDave
KayakDave

Reputation: 24676

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.net/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.com/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.

Upvotes: 2

Zach Snow
Zach Snow

Reputation: 1044

  1. Convert your flat list of items to a list of lists of 3 items.
  2. 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.

Upvotes: 1

Satpal
Satpal

Reputation: 133403

You 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

Upvotes: 3

Related Questions