Loop variable built-ins

Note:

Loop variable built-ins only exists since FreeMarker 2.3.23.

These built-ins you can only use with the loop variable of the list and items directives (and of the deprecated foreach directive). Some explanation of that follows (loopVar?index returns the 0-based index in the listable value we iterate through):

Template
<#-- Note: x is a loop variable -->
<#list ['a', 'b', 'c'] as x>
  ${x?index}
</#list>
Output
0
1
2

When the list directive doesn't specify the loop variable, these built-ins are used with the loop variable of the items directive:

Template
<#list ['a', 'b', 'c']>
  <ul>
   <#items as x>
     <li>${x?index}</li>
   </#items>
  </ul>
</#list>

Loop variable built-ins only use the name of loop variable, so that they can identify the related ongoing iteration. They don't read the value of the loop variable. Hence, this is a parsing error:

Template
<#list ['a', 'b', 'c'] as x>
  <#assign y = x>
  ${y?index} <#-- ERROR: y isn't a loop variable -->
</#list>

counter

Note:

This built-in is available since FreeMarker 2.3.23.

Returns the 1-based index where the iteration (which is identified by the loop variable name) currently stands.

Template
<#list ['a', 'b', 'c'] as i>
  ${i?counter}: ${i}
</#list>
Output
  1: a
  2: b
  3: c
Note:

For the 0-based index, use the index built-in.

has_next

Note:

This built-in is available since FreeMarker 2.3.23.

Tells if the item where the iteration (which is identified by the loop variable name) currently stands is not the last item.

Template
<#list ['a', 'b', 'c'] as i>${i?has_next?c} </#list>
Output
true true false 
Note:

For separating items with commas and such, use <#sep>separator</#sep> instead of <#if var?has_next>separator</#if>, as it's more readable. (Furthermore the </#sep> can be often omitted, like in <#list ... as var>...${var}...<#sep>separator</#list>)

Note:

If you need the inverse of this built-in, use var?is_last instead of !var?has_next, because it's more readable.

index

Note:

This built-in is available since FreeMarker 2.3.23.

Returns the 0-based index where the iteration (which is identified by the loop variable name) currently stands.

Template
<#list ['a', 'b', 'c'] as i>
  ${i?index}: ${i}
</#list>
Output
  0: a
  1: b
  2: c
Note:

For the 1-based index, use the counter built-in.

is_even_item

Note:

This built-in is available since FreeMarker 2.3.23.

Tells if the item where the iteration (which is identified by the loop variable name) currently stands has an even 1-based index.

Template
<#list ['a', 'b', 'c', 'd'] as i>${i?is_even_item?c} </#list>
Output
false true false true
Note:

To make tables with alternating row colors and such, use var?item_parity or var?item_cycle(...) instead.

is_first

Note:

This built-in is available since FreeMarker 2.3.23.

Tells if the item where the iteration (which is identified by the loop variable name) currently stands is the first item.

Template
<#list ['a', 'b', 'c'] as i>${i?is_first?c} </#list>
Output
true false false 

is_last

Note:

This built-in is available since FreeMarker 2.3.23.

Tells if the item where the iteration (which is identified by the loop variable name) currently stands is the last item.

Template
<#list ['a', 'b', 'c'] as i>${i?is_last?c} </#list>
Output
false false true
Note:

If you need the inverse of this built-in, use var?has_next instead of !var?is_last, because it's more readable.

Note:

For separating items with commas and such, use <#sep>separator</#sep> instead of <#if var?has_next>separator</#if>, as it's more readable. (Furthermore the </#sep> can be often omitted, like in <#list ... as var>...${var}...<#sep>separator</#list>)

is_odd_item

Note:

This built-in is available since FreeMarker 2.3.23.

Tells if the item where the iteration (which is identified by the loop variable name) currently stands has an odd 1-based index.

Template
<#list ['a', 'b', 'c', 'd'] as i>${i?is_odd_item?c} </#list>
Output
true false true false 
Note:

To make tables with alternating row colors and such, use var?item_parity or var?item_cycle(...) instead.

item_cycle

Note:

This built-in is available since FreeMarker 2.3.23.

This is a more generic version of the item_parity built-in, where you can specify what value to use instead of "odd" and "even". It also allows more than 2 values that it will cycle through.

Template
<#list ['a', 'b', 'c', 'd', 'e', 'f', 'g'] as i>
  <tr class="${i?item_cycle('row1', 'row2', 'row3')}">${i}</tr>
</#list>
Output
  <tr class="row1">a</tr>
  <tr class="row2">b</tr>
  <tr class="row3">c</tr>
  <tr class="row1">d</tr>
  <tr class="row2">e</tr>
  <tr class="row3">f</tr>
  <tr class="row1">g</tr>

Some details:

  • The number of arguments must be at least 1, and has no upper limit.

  • The type of the arguments can be anything, they doesn't have to be strings.

Note:

Use the item_parity built-in instead if the values you need are "odd" and "even".

item_parity

Note:

This built-in is available since FreeMarker 2.3.23.

Returns "odd" or "even" string value, depending on the parity of the 1-based index where the iteration (which is identified by the loop variable name) currently stands. This is commonly used for alternating color for table rows:

Template
<#list ['a', 'b', 'c', 'd'] as i>
  <tr class="${i?item_parity}Row">${i}</tr>
</#list>
Output
  <tr class="oddRow">a</tr>
  <tr class="evenRow">b</tr>
  <tr class="oddRow">c</tr>
  <tr class="evenRow">d</tr>
Note:

Use the item_parity_cap built-in for capitalized "Odd" and "Even". Use the item_cycle built-in to specify custom values, or more then two values.

item_parity_cap

Note:

This built-in is available since FreeMarker 2.3.23.

Returns "Odd" or "Even" string value (note the capitalization), depending on the parity of the 1-based index where the iteration (which is identified by the loop variable name) currently stands.

Template
<#list ['a', 'b', 'c', 'd'] as i>
  <tr class="row${i?item_parity_cap}">${i}</tr>
</#list>
Output
  <tr class="rowOdd">a</tr>
  <tr class="rowEven">b</tr>
  <tr class="rowOdd">c</tr>
  <tr class="rowEven">d</tr>
Note:

Use the item_parity built-in for lower case "odd" and "even".