Velocity Template Language: Directives

Introduction to Directives

References allow template designers to generate dynamic content for web sites.
Directive allow to introduce some business logic to change appearance and content of the web site.

Remember that:

References begin with $ and are used to get something.
Directives begin with # and are used to do something.

Like references, the name of the directive may be bracketed by a { and a } symbol.
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 brackets, as demonstrated:

  • #set( $primate = “monkey” )
  • #set( $customer.Behavior = $primate )

All this are valid SET Directives:

  • #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

Assignements can also be done with simple arithmetic expression:

  • #set( $value = $foo + 1 )
  • #set( $value = $bar – 1 )
  • #set( $value = $foo * $bar )
  • #set( $value = $foo / $bar )

Null values cannot be assigned.

Once a value has been added to context (setted), it cannot be assigned back to NULL.
Velocity  does not allow that a reference is removed from script context assigning it to NULL.

Double Quotes and Single Quotes: String Literals.

When using the #set directive, string literals that are enclosed in double quote characters will be parsed and rendered, as shown:

VLC. Literal

The output is:

VTL

However, when the string literal is enclosed in single quote characters, it will not be parsed:

The output is:

Don’t parse me! Please.

If you need to render many lines of unparsed code, you can adopt the
#[[don't parse me!]]#
syntax.

Render as:

Conditionals: #if, #elseif, #else

All directives, except for #set, are terminated from #end.

The #if directive allow to “condition” inclusion of text in web page only if statement is True.
This statement will print “Velocity!” only if $foo is true:

$foo is considered valid only if is a boolean value TRUE or if is not null.

An #elseif or #else element can be used with an #if element. Note that the Velocity Templating Engine will stop at the first expression that is found to be true. In the following example, suppose that $foo has a value of 15 and $bar has a value of 6.

In this example, $foo is greater than 10, so the first two comparisons fail. Next $bar is compared to 6, which is true, so the output is Go South.

Relational and Logical Operators: Equals(==), And(&&),  Or(||), Not(!)

Equivalent

In Velocity the equivalent operator (==) can be used to directly compare numbers, strings, or objects.
When the objects are of different classes, the string representations are obtained by calling toString() for each object and then compared.

And, Or and Not

Logical AND and OR operators work the same way, except that in OR only one of the references need evaluate to true in order for the entire expression to be considered true.

With logical NOT operators, there is only one argument :

There are text versions of all logical operators, including eq, ne, and, or, not, gt, ge, lt, and le.

Loops: #foreach

The #foreach element allows for looping. For example:

This #foreach loop causes the $allProducts list (the object) to be looped over for all of the products (targets) in the list. Each time through the loop, the value from $allProducts is placed into the $product variable.

If $allProducts is an Hashtable the loop should be this:

Velocity provides an easy way to get the loop counter so that you can do something like the following:

If you want a zero-based index of the #foreach loop, you can just use $foreach.index instead of $foreach.count.

Velocity also now provides an easy way to tell if you are on the last iteration of a loop:

Likewise, $foreach.first and $foreach.last are provided to compliment $foreach.hasNext. If you want to access these properties for an outer #foreach loop, you can reference them directly through the $foreach.parent or $foreach.topmost properties (e.g. $foreach.parent.index or $foreach.topmost.hasNext).

Range Operator: [n..m]

The range operator [n..m] can be used in conjunction with #set and #foreach statements. Useful for its ability to produce an object array containing integers, the range operator can be used like this:

Produces the following output:

Note that the range operator only produces the array when used in conjunction with #set and #foreach directives, as demonstrated in the fourth example.

Web page designers concerned with making tables a standard size, but where some will not have enough data to fill the table, will find the range operator particularly useful.

 

Stop loops and template rendering: #break and #stop.

#break

The #break directive stops any further rendering of the current execution scope.

If you wish to break out of a specific execution scope that is not necessarily the most immediate one, then you can pass the scope control reference (i.e. $foreach, $template, $evaluate, $define, $macro, or $somebodymacro) as an argument to #break. (e.g. #break($macro)). This will stop rendering of all scopes up to the specified one. When within nested scopes of the same type, remember that you can always access the parent(s) via $<scope>.parent or $<scope>.topmost and pass those to #break instead (e.g. #break($foreach.parent) or #break($macro.topmost)).

#stop

The #stop directive stops any further rendering and execution of the template.
For debugging purposes, you may provide a message argument (e.g. #stop(‘$foo was not in context’) ) that will be written to the logs (DEBUG level, of course) upon completion of the stop command.

Macro and Template blocks.

#define

The #define directive lets one assign a block of VTL to a reference.

The example below will display Hello World!.

#macro

The #macro script element allows template designers to define a repeated segment of a VTL template.
Velocimacros are very useful in a wide range of scenarios both simple and complex.
This Velocimacro, created for the sole purpose of saving keystrokes and minimizing typographic errors, provides an introduction to the concept of Velocimacros.

The Velocimacro being defined in this example is d, and it can be called in a manner analogous to any other VTL directive:

#d()

Macro are really powerful because accept parameters:

In example above the macro is called passing a parameter:  #@d()Hello!#end
The output will be:

<tr><td>Hello!</td></tr>

In above example $bodyContent is a reserved internal variable that Velocity uses to assign passed value.
But you can declare a macro accepting more input parameters, the important is that you call later with same parameters.

The macro #tablerows can be used like this:

Velocimacros can take as arguments any of the following VTL elements :

  • Reference : anything that starts with ‘$’
  • String literal : something like “$foo” or ‘hello’
  • Number literal : 1, 2 etc
  • IntegerRange : [ 1..2] or [$foo .. $bar]
  • ObjectArray : [ "a", "b", "c"]
  • boolean value true
  • boolean value false

Escaping special Characters: Getting literal

VTL uses special characters, such as $ and #, to do its work. But sometime you may need to print those characters in your output.

When you write currency there is no problem because the reference must begin with a letter and $2.5 cannot be confused with a valid reference.

However, escaping character is best way to print special characters using backslash (\).

Renders as: