2

I'm wondering how to implement a task (which is very easy in server-side templating) in angular like:

{{ if condition }}
    <div class="container">
{{ endif }}

    <div class="child"></div>

{{ if condition }}
    </div> <!-- closing container -->
{{ endif }}

I'm of course aware of ng-hide, ng-show and ng-hide... but it think I can't use these directives to implement my task... so what should I do?

ps: I can't do the following:

<div class="container" ng-if="condition">
    <div class="child"></div>
</div>
<div class="child" ng-if="!condition"></div>

because I'm using the module operator (%) in order to wrap "child" nodes into "container" every X element (where X is a dynamic parameter)

the final result would be (supposing X is 4):

<div class="container">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
</div>
<div class="container">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
</div>

... and so on (I'm in a ng-repeat)

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
daveoncode
  • 18,900
  • 15
  • 104
  • 159

2 Answers2

3

Group by filter in the template :

The key part of the solution is that we are computing a property containerId, which depends on the container size and on the index of the element in the array :

$scope.arrayItems.forEach(function(item, index) {
    item.containerId = Math.floor(index / size);
});

Then in the template we group the elements by the property containerId :

<div class="container" ng-repeat="containers in arrayItems | groupBy: 'containerId'">
    <div class="child" ng-repeat="item in containers">{{item.name}}</div>
</div>

That groupBy filter in the template comes from angular-filter

See fiddle


Group by in the controller:

In case you don't want to add angular-filter as a dependency, you could group the elements in the controller. The following example makes use of the groupBy function of lodash :

In the controller :

$scope.itemsGroupedByContainer = _.groupBy($scope.arrayItems, 'containerId');

In the template :

<div class="container" ng-repeat="containers in itemsGroupedByContainer">
    <div class="child" ng-repeat="item in containers">{{item.name}}</div>
</div>

See fiddle

Michel
  • 26,600
  • 6
  • 64
  • 69
1

I think that you need the ng-repeat directive. Try something like this:

<div ng-repeat="item1 in repeat1 track by $index">

    <div ng-repeat="item2 in repeat2 track by $index"></div>

</div>

Docs: https://docs.angularjs.org/api/ng/directive/ngRepeat

You don't need an if block to add a closing </div>

kevinius
  • 4,232
  • 7
  • 48
  • 79
  • I'm already using an ng-repeat! but I'm not barely printing a list of elements, I need to group them by a certain number of items :P – daveoncode Mar 18 '15 at 16:49
  • So you need to create dom nodes based on a variable? – kevinius Mar 18 '15 at 16:53
  • yes, I have a collection of N elements and I need to group them in a container of X items... so If I have 40 elements and X is 4 I will have 10 container nodes containg 4 elements – daveoncode Mar 18 '15 at 16:55
  • So the outer repeater is iterating over the amount of containers (40/x = 10). And the inner repeater will iterate over the elements. Try some ideas on this page: http://stackoverflow.com/questions/14198017/iteration-ng-repeat-only-x-times-in-angularjs – kevinius Mar 18 '15 at 17:07