#foreach iterates over the elements given in a
List or Array element.
Example 5.5. foreach loop example
<ul> #foreach( $product in $allProducts ) <li>$product</li> #end </ul>
Unlike other languages, the Velocity templating language allows
only loops where the number of iterations is predetermined. There is no
repeat..until loop in
Velocity. This has been a conscious decision to make sure that the
rendering process of Velocity does always terminate.
A VTL foreach loop takes two arguments, the first one is the loop variable and the second is an object that can be iterated over. Velocity supports a number of object types in its default configuration:
Any array type
java.lang.Collection The loop iterates
over the Iterator returned by obj.iterator()
java.lang.Map The loop will iterate over
the values of the Map using the iterator returned by
java.lang.Iterator Velocity uses this
java.lang.Enumeration Velocity wrapping
the Enumeration into an Iterator
Using an Iterator or Enumeration object directly in a template has the side effect that the loop cannot be evaluated multiple times because the loop consumes the object that gets iterated. Be especially careful if you use such an object inside a Macro or an included template.
Velocity provides you with a loop counter reference which contains the number of the current iteration of the loop:
<table> #foreach( $customer in $customerList ) <tr><td>$velocityCount</td><td>$customer.Name</td></tr> #end </table>
The default name for the loop counter and its starting value is
specified through runtime properties. By default it starts at 1 and is
# Default name of the loop counter # variable reference. directive.foreach.counter.name = velocityCount # Default starting value of the loop # counter variable reference. directive.foreach.counter.initial.value = 1
The Velocity loop counter variable does support nested loops, so the following example would work as expected:
Example 5.6. Nested Loops and the loop counter
#foreach ($category in $allCategories) Category # $velocityCount is $category #foreach ($item in $allItems) Item # $velocitycount is $item #end #end
The loop counter is local to its surrounding loop and any inner loops hides but not resets it. Please note that it is not possible to access the count variable of the outer loop directly inside the inner loop.
To avoid deadlocks and denial of service attacks, it is possible to set a maximum allowed number of times that a loop may be executed. By default there is no limit, but it can be set to an arbitrary number in the Velocity configuration.
# The maximum allowed number of loops. directive.foreach.maxloops = -1
 It is stil possible to write a template that contains endless loops. It is just harder.
 The list of objects can be changed and extended, please see the Developers guide on how to do this.
 You can assign its value to another variable before entering
the inner loop using
#set and access it through
this variable inside the inner loop.