add bootstrap rows during ng-repeat

16,667

Solution 1

Here a simple solution with just HTML, 3 ROWS

<div class="row" >
    <div class="col-md-4" ng-repeat-start="item in data">
        I'M A ROW
    </div>
    <div class="clearfix" ng-if="($index+1)%3==0"></div>
    <div ng-repeat-end=""></div>
</div>

Solution 2

If you start by chunking your data into smaller parts, based on the number of columns, it will be easy to use nested ng-repeats to create your layout:

$scope.getRows = function(array, columns) {
  var rows = [];

  //https://stackoverflow.com/questions/8495687/split-array-into-chunks
  var i,j,temparray, chunk = columns;
  for (i=0,j=array.length; i<j; i+=chunk) {
      temparray = array.slice(i, i+chunk);

      rows.push(temparray);
  }

  return rows;
};

$scope.rows = $scope.getRows($scope.contestData, $scope.columns);

Then your markup is simply:

<div ng-repeat="row in rows">
  <div class="row">
    <div ng-class="{'col-xs-4': columns == 3, 'col-xs-3': columns == 4}" ng-repeat="contest in row">
      <div class="panel panel-primary">
          <div class="panel-heading">
            <h3 class="panel-title">{{contest}}</div>
          </div>
      </div>
    </div>
  </div>
</div>

Notice that ng-class is doing the work of deciding which type of class to add based on the number of columns. This example is handing 3 and 4, but you could extend it to handle others.

Here is a working demo: http://plnkr.co/edit/B3VAXlq9dkzO3hQkbkN3?p=preview

Update:
Plunker's full screen mode seems to interfere with the column width style, so I changed the link to display in preview mode.

Solution 3

Answering my own question here, similar to the answer from j.wittwer, I created a filter to chunk my data appropriately by row, etc.:

angular.module('myApp.filters').
    filter('rowfilter', function () {
        return function (data, columnCount) {
            var rows = [];
        var colCount = columnCount || 2;
        var columns = [];
        for (var i = 0; i< data.length; i++) {
        columns.push(data[i]);
        if (columns.length == colCount) {
        rows.push(columns);
        columns = [];
        }
        }
        if (columns.length > 0) {
        rows.push(columns);
        }
        return rows;
        };
    });

And then I use the filter (jade shown here): .row(ng-repeat="row in contestData.classData | rowfilter") .col-sm-6(ng-repeat="column in row")

Works very nicely, still wrapping my head around Angular!

Solution 4

I have this decision, seems to be working for 3 col

<div ng-repeat="r in data">
    <div class="row" ng-if="$index%3==0">
        <div class="col-md-4" ng-if="$index<data.length">
        {{data[$index]}}
        rrr
        </div>
        <div class="col-md-4" ng-if="$index+1<data.length">
        {{data[$index+1]}}
        rrr
        </div>
        <div class="col-md-4" ng-if="$index+2<data.length">
        {{data[$index+2]}}
        rrr
        </div>
    </div>
</div>

and data is

$scope.data = ['1','2','3','4','5','6','7'];
Share:
16,667
Admin
Author by

Admin

Updated on July 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a situation where I have a list of data to be displayed in individual panels, Using Bootstrap's grid system, I'd like to take advantage of a wide screen and display several panels horizontally, but on narrow screens have them stack. I'm currently laying things out on the server side with ejs like this, with columns being passed in as a query parameter, typically set to 2 or 3, so each colClass is either col-sm-6 or col-sm-4.

    <% var colWidth = 12/columns; var colClass = "col-sm-" + colWidth; %>
    <% for(var i=0; i<contestData.classData.length; i++) {%>
        <% if ((classCount % columns) == 0) { %>
            <div class="row">
        <% } %>
        <div class="<%= colClass %>">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title"> <%= contestData.classData[i].name %> </h3>
                </div>
                <div>...</div>
            </div>
        </div>
        <% classCount++ %>
        <% if ((classCount % columns) == 0) { %>
            </div>
        <% } %>
    <% } %>
    

    This works, but doing this level of layout on the server side offends me, I'd really rather do this with Angular but I can't figure out how to wrap the appropriate number of panels in a div with class=row while doing ng-repeat or even ng-repeat-start="classData in contestData.classData"

    Thanks!