Angular.js using bootstrap and dynamically creating rows

I am trying to figure out how to dynamically create bootstrap row divs with a class of row-fluid with angular.js using the ng-repeat directive.

Here is the angular:

 <div ng-repeat="task in tasks" class="row-fluid">
     <div class="span6 well">{{task.name}}</div>
 </div>

This does not work though. The bootstrap html I wish to generate is:

Basically I need to do mod 2 of the index inside of the ng-repeat, and if its 0, close out the </div> and create a new <div class="row-fluid">. How is this possible?


ANSWERS:


The idea is to filter your items in order to group them, and make a second ngRepeat to iterate on sub-items.

First, add that filter to your module :

module.filter('groupBy', function() {
    return function(items, groupedBy) {
        if (items) {
            var finalItems = [],
                thisGroup;
            for (var i = 0; i < items.length; i++) {
                if (!thisGroup) {
                    thisGroup = [];
                }
                thisGroup.push(items[i]);
                if (((i+1) % groupedBy) === 0) {
                    finalItems.push(thisGroup);
                    thisGroup = null;
                }
            }
            if (thisGroup) {
                finalItems.push(thisGroup);
            }
            return finalItems;
        }
    };
});

In your controler (because if you filter directly in your template, then you will have a $digest loop):

function TaskCtrl() {
    $scope.tasksGroupBy2 = $filter('groupBy')(taskGroup, 2);
}

And in your .html :

<div ng-repeat="taskGroup in tasksGroupBy2" class="row-fluid">
    <div ng-repeat="task in taskGroup" class="span6 well">{{task.name}}</div>
</div>

As an improvement to the answer Anthony gave, I would say that you could save yourself a lot of trouble using the slice method instead of going through all those conditions.

Try defining your filter as it follows:

module.filter('group', function() {
    return function(items, groupItems) {
        if (items) {
            var newArray = [];

            for (var i = 0; i < items.length; i+=groupItems) {
                if (i + groupItems > items.length) {
                    newArray.push(items.slice(i));
                } else {
                    newArray.push(items.slice(i, i + groupItems));
                }
            }

            return newArray;
        }
    };
});

After that you can call the filter on your controller as Anthony pointed out in his response:

function Controller ($scope) {
    $scope.itemsGrouped = $filter('group')(itemsArray, 5);
}

Off Topic: using bootstrap you can just place divs of class="span6 well" into one bigass row as they will stack nicely. (You will get an responsive layout too). Sorry if it was just an example of the behaviour that bootstrap can't handle. Anthony and Remigio are right; you have to create an extra module vehicle that will generate divs immersed into your ng-repeated tags.



 MORE:


 ? AngularJS use a function in a controller to return data from a service to be used in ng-repeat
 ? AngularJS InfDig error (infinite loop) with ng-repeat function that returns array of objects
 ? How can I make a click event inside ng-repeat only re-render the affected item (i.e., not run $apply)?
 ? angular Infinite $digest Loop in ng-repeat
 ? Angular ng-repeat - creating collection dynamically
 ? Why is a function in ng-repeat called several times?
 ? How to sort a 1:1 object map in Angular JS ng-repeat
 ? Angular ng-repeat how to unwrap promise in template for each item
 ? AngularJS ng-repeat is not looping through array
 ? How to show a div when a filtered list is empty (Filtered using ng-repeat with ng-if)