Austin
Austin

Reputation: 3080

Customize ng-repeat in AngularJS for every nth element

I am trying to customize an ng-repeat to add something like a br tag to every 4th element. I have tried searching around but cannot seem to find a solid answer. Is there a simple way to add conditions to Angular for something like this? my ng-repeat is just adding some spans with content in them, but I need to start a new line every 4th element.

i.e. I want the following

item1 item2 item3 item4 item5 item6 item7 item8

but right now it just does this

item1 item2 item3 item4 item5 item6 item7 item8

If there are any good articles relating to ng-repeat customization (for newbies) I would be thankful for links as well as everything I have found thus far is too difficult to understand.

HTML

  <div class="section">
    <div ng-repeat="items in MyList">
      <img ng-click="AddPoint($index)" src={{items.image}} />
      <span>{{items.currentPoint}}/{{items.endPoint}}</span>
    </div>
  </div>

Upvotes: 13

Views: 27165

Answers (4)

Nate Bosscher
Nate Bosscher

Reputation: 647

I'm sure you've solved your issue by now. But in the future, why not separate your list in javascript rather than on the front end. Just do some pre-rendering processing to get an object like this:

// convert this
var list = ["item 1", "item 2", "item 3", "item 4", "item 5", "item 6"];

// into this

var list = [
  ["item 1", "item 2", "item 3"],
  ["item 4", "item 5", "item 6"]
];

// you could use a function like this
function convertToRowsOf3(list) {
  var newList = [];
  var row;
  
  for(var i = 0; i < list.length; i++){
    if(i % 3 == 0){ // every 3rd one we're going to start a new row
      if(row instanceof Array)
        newList.push(row); // if the row exists add it to the newList
      
      row = [] // initalize new row
    }
    
    row.push(list[i]); // add each item to the row
  }
  
  if(row.length > 0) {
    newList.push(row);
  }
  
  return newList;
}
<span ng-repeat="row in list">
  <span ng-repeat="col in row" ng-bind="col"></span><br>
</span>

Upvotes: 3

helius
helius

Reputation: 51

PSL's solution is for shure the neater one, but.. I got the same problem and in the end solved it in the following way (for those not wanting to tweak CSS or are not so into it)

<div class="row responsive-sm" ng-repeat="exercise in exercises" ng-if="$even">
  <div class="col col-50">
    <div class="item item-stacked-label">
      {{exercise.title}}
    </div>
    ....
  </div>
  <div class="col col-50" ng-if="!$last" ng-init="exercise = exercises[$index+1]">
    <div class="item item-stacked-label">
      {{exercise.title}}
    </div>
    ....
  </div>
</div>

Here I had to put 2 exercises each row and just used ng-init to set again the actual picked one (exercise) to the next ($index+1) on each copy. Mind the !$last in the ng-if, without the output may corrupt the page as there are no more elements in the array to display

Upvotes: 2

Phil Hudson
Phil Hudson

Reputation: 3901

This is how I achieved inserting a row every 6 items:

<div ng-class='row' ng-if="$index % 6 ? 'row' : ''" ng-repeat="genreNav in genres track by $index">

      <img src="{{genreNav.image}}" class="thumbnail img-responsive">

</div>

Upvotes: 0

PSL
PSL

Reputation: 123739

You could just use $index and apply it with ng-if on <br ng-if="!($index%4)" />

<div class="section">
    <div ng-repeat="items in MyList">
      <img ng-click="AddPoint($index)" src={{items.image}} />
      <span>{{items.currentPoint}}/{{items.endPoint}}</span>
      <br ng-if="!(($index + 1) % 4)" />
    </div>
  </div>

Update

Based on the comment, you just need css for this just clear the float every nth element.

.section > div:nth-of-type(4n+1){
  clear:both;
}

Demo

If you are worried about support for older browsers then just add a class on specific condition:-

 <div ng-repeat="items in offensiveMasteries" ng-class="{wrap:!($index % 4)}">

and a rule for .section > div.wrap

Demo

Upvotes: 34

Related Questions