References allow template designers to generate dynamic content for Web sites, while
directives
-- easy to use script elements that can be used to
creatively manipulate the output of Java code -- permit Web designers to truly take
charge of the appearance and content of the Web site.
Directives always begin with a #. Like references, the name of the directive may be bracketed by "{" and "}" symbols. This is useful with directives that are immediately followed by text. For example the following produces an error:
#if($a==1)true enough#elseno way!#end
In such a case, use the brackets to separate #else from the rest of the line.
#if($a==1)true enough#{else}no way!#end
#set
The #set
directive is used for setting the value of a reference. A
value can be assigned to either a variable reference or a property reference, and
this occurs in parentheses:
#set( $primate = "monkey" )
#set( $customer.Behavior = $primate )
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
- ArrayList
- Map
These examples demonstrate each of the aforementioned types:
#set( $monkey = $bill ) ## variable reference
#set( $monkey.Friend = "monica" ) ## string literal
#set( $monkey.Blame = $whitehouse.Leak ) ## property reference
#set( $monkey.Plan = $spindoctor.weave($web) ) ## method reference
#set( $monkey.Number = 123 ) ##number literal
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
#set( $monkey.Map = {"banana" :"good", "roast beef" : "bad"}) ## Map
Similarly, for the Map example, the elements defined within the { } operator are accessible using the methods defined in the Map class. So, for example, you could access the first element above using $monkey.Map.get("banana") to return a String 'good', or even $monkey.Map.banana to return the same value.
The RHS can also be a simple arithmetic expression:
#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )
If the RHS is a property or method reference that evaluates to null
,
it will not be assigned to the LHS. Depending on how Velocity is configured,
it is usually not possible to remove an existing reference from the context via this
mechanism. (Note that this can be done by changing one of the Velocity configuration
properties). This can be confusing for newcomers to Velocity. For example:
#set( $result = $query.criteria("name") )
The result of the first query is $result
#set( $result = $query.criteria("address") )
The result of the second query is $result
If $query.criteria("name")
returns the string "bill", and
$query.criteria("address")
returns null
, the
above VTL will render as the following:
The result of the first query is bill
The result of the second query is bill
This tends to confuse newcomers who construct #foreach
loops that
attempt to #set
a reference via a property or method reference,
then immediately test that reference with an #if
directive. For
example:
#set( $criteria = ["name", "address"] )
#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). The
details of the #if
and #foreach
directives are
covered later in this document.
One solution is to pre-set $result
to false
. Then
if the $query.criteria()
call fails, you can check.
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
Unlike some of the other Velocity directives, the
#set
directive does not have an #end
statement.
Literals
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( $foo = "bar" )
$foo
#set( $blargh = '$foo' )
$blargh
This renders as:
bar
$foo
By default, this feature of using single quotes to render unparsed text is available
in Velocity. This default can be changed by editing
velocity.properties
such that
stringliterals.interpolate=false
.
Alternatively, the #literal
script element allows the template
designer to easily use large chunks of uninterpreted content in VTL code. This can
be especially useful in place of escaping multiple directives:
#literal()
#foreach ($woogie in $boogie)
nothing will happen to $woogie
#end
#end
Renders as:
#foreach ($woogie in $boogie)
nothing will happen to $woogie
#end