Search code examples
htmlacceleo

Acceleo: dynamically generate HTML grid in a for loop


I'm using Acceleo 3.0 to generate some html code from an EMF Model. I have the following code:

<div class="ui-grid" style="text-align:center">
    [for ( icon : Icon | self.Icons )]
            <div class="column-a"><button data-icon="[iconName/]"></button></div>
            <div class="column-b"><button data-icon="[iconName/]"></button></div>
            <div class="column-c"><button data-icon="[iconName/]"></button></div>
    [/for]
</div>

Now, what I would like to do is to make it fully parametric, incrementally applying classnames in the for loop until I reach a MaxColumns parameter in my model, then starting over from 0. I.e, if I have MaxColumns = 3 I would like the following result:

<div class="ui-grid" style="text-align:center">
  <div class="column-a"><button data-icon="icon-1"></button></div>
  <div class="column-b"><button data-icon="icon-2"></button></div>
  <div class="column-c"><button data-icon="icon-3"></button></div>
  <div class="column-a"><button data-icon="icon-4"></button></div>
  <div class="column-b"><button data-icon="icon-5"></button></div>
  <div class="column-c"><button data-icon="icon-6"></button></div>
  <div class="column-a"><button data-icon="icon-7"></button></div>
  <div class="column-b"><button data-icon="icon-8"></button></div>
  <div class="column-c"><button data-icon="icon-9"></button></div>
  ...
</div>

Thanks in advance.


Solution

  • Supposing your MaxColumn attribute is onwed by self (in the context you describe), you can use the subSequence(start, end) operator on Icons if this reference is a sequence. Here is the code:

    <div class="ui-grid" style="text-align:center">
    [for ( icon : Icon | self.Icons->subSequence(1, self.MaxAttribute) )]
            <div class="column-a"><button data-icon="[iconName/]"></button></div>
            <div class="column-b"><button data-icon="[iconName/]"></button></div>
            <div class="column-c"><button data-icon="[iconName/]"></button></div>
    [/for]
    

    If your reference is not a sequence (but ordered, so an OrderedSet):

    <div class="ui-grid" style="text-align:center">
    [for ( icon : Icon | self.Icons->asSequence()->subSequence(1, self.MaxAttribute) )]
            <div class="column-a"><button data-icon="[iconName/]"></button></div>
            <div class="column-b"><button data-icon="[iconName/]"></button></div>
            <div class="column-c"><button data-icon="[iconName/]"></button></div>
    [/for]
    

    However, keep in mind that if your ref. is not ordered, Acceleo could collect collection elements in a different order for each execution. The use of the asSequence() would not change anything.

    Also, be careful, collection first index is 1, not 0.