References allow template designers to generate dynamic content for web sites, while Directives permit web designers to truly take charge of the appearance and content of the web site. A directive is a script element that can be used to manipulate the rendering of the template.
As described in Chapter 3.1, Velocity Directives are part of either
single or multi-line statements and are preceded by a hash sign
(#
). While the hash sign is technically not part of the
directive, we will still speak about the #if
or
#set
directive.
Velocity knows about the following directives:[7]
#set()
(single line statement)
#literal()
(multi line statement)
#if() / #elseif() / #else
(multi line
statement)
#foreach()
(multiline statement)
#include()
(single line statement)
#parse()
(single line statement)
#stop()
(single line statement)
#macro()
(multi line statement, see Chapter
7)
The #set
directive is used for setting the
value of a reference. It is used in a single-line statement.
A value can be assigned to either a variable reference or a property reference.
Example 5.1. Value assignment using the set directive
## Assigning a variable value #set( $fruit = "apple" ) ## Assigning a property value #set( $customer.Favourite = $fruit )
The left hand side (LHS) of the assignment must be a variable reference or a property reference. The right hand side (RHS) can be one of the following types:
Variable reference
String literal
Property reference
Method reference
Number literal
List
Map
Expression
Example 5.2. Valid reference assignments
## variable reference #set( $fruit = $selectedFruit ) ## string literal #set( $fruit.flavor = "sweet" ) ## property reference #set( $fruit.amount = $cart.total ) ## method reference #set( $fruit.color = $colorlist.selectColor($select) ) ## number literal #set( $fruit.value = 123 ) ## List #set( $fruit.sorts = ["Apple", "Pear", "Orange"] ) ## Map #set( $fruit.shapes = {"Apple" : "round", "Pear" : "conical"})
![]() | Note |
---|---|
For the List example the elements defined with the
Similarly, for the Map example, the elements defined within the
|
The RHS can also be an arithmetic expression as described in the Math chapter below.
Example 5.3. Expression examples
#set( $value = $foo + 1 ) #set( $value = $bar - 1 ) #set( $value = $foo * $bar ) #set( $value = $foo / $bar )
In its default configuration, Velocity treats
null
values on the RHS special. If your developers
don't change the default configuration, you must understand that it is
not possible to assign a null value through a set
directive to a reference. Starting with Velocity 1.5, a runtime
property (directive.set.null.allowed
) exists that
removes this restriction. If you do not want null
values to be treated special, tell your application developers that
they should look up this property in the Velocity Developers
Guide and set it to true.
![]() | Note |
---|---|
Removing this restriction is one of the new features of Velocity 1.5. If you are maintaining existing template code from older Velocity versions, you probably want to keep the old behaviour. For new developments based on Velocity 1.5 and beyond, we
strongly recommend that you don't treat null values on the RHS
special (set |
The remainder of this chapter assumes that you kept the default configuration of Velocity.
If the RHS is a property or method reference that evaluates to
null
, it will not be assigned
to the LHS and the LHS will not be altered. This
is very different from the behaviour in e.g. the Java programming
language and needs some discussion.
In the following piece of code, two queries are executed using the same set of template references:
#set( $result = $query.criteria("fruit") ) The result of the first query is $result #set( $result = $query.criteria("customer") ) The result of the second query is $result
If $query.criteria("name")
returns the string
"apple", and $query.criteria("customer")
returns
null, the above VTL will render as the follows:
The result of the first query is apple The result of the second query is apple
In the second set
directive, the RHS is null,
because $query.criteria("customer")
returned null.
So the RHS will not be modified (and the old value retained).
Unfortunately, this can lead to hard-to-detect errors, for
example with #foreach
loops that attempt to change
a reference using a #set
directive, then
immediately test that reference with an #if
directive:
#set( $criteria = ["fruit", "customer"] ) #foreach( $criterion in $criteria ) #set( $result = $query.criteria($criterion) ) #if( $result ) Query was successful #end #end
In the above example, it would not be wise to rely on the
evaluation of $result
to determine if a query was
successful. After $result
has been set (added to
the context), it cannot be set back to null (removed from the
context).
One solution to this would be to reset the value of
$result
in every loop iteration:
#set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) #set( $result = "" ) #set( $result = $query.criteria($criterion) ) #if( $result != "" ) Query was successful #end #end
However, the easiest way is to use the quiet reference notation:
#set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) #set( $result = $!query.criteria($criterion) ) #if( $result != "" ) Query was successful #end #end
If the query fails, $result
gets the empty
string assigned.
When using the #set
directive, string
literals that are enclosed in double quote characters will be parsed
and rendered, as shown:
#set( $directoryRoot = "www" ) #set( $templateName = "index.vm" ) #set( $template = "$directoryRoot/$templateName" ) $template
The output will be
www/index.vm
However, when the string literal is enclosed in single quote characters, it will not be parsed:
#set( $fruit = "apple" ) $fruit #set( $veggie = '$fruit' ) $veggie
This renders as:
apple $fruit
By default, rendering unparsed text using single quotes is
activated in Velocity. This default can be changed by changing the
runtime.interpolate.string.literals
property to be
false. (See the Velocity Developers Guide for
more information).
[7] If is possible to add custom directives through the Velocity configuration. These are merely the directives shipped with the default Velocity configuration. It is even possible to turn some of these off.