FreeMarker Expressions

A FreeMarker expression within an output escape sequence refers to a scalar in the root hash of the data model. This is either a string or a numerical value that will be output directly as text:

${foo}
	

Note that FM version 2.0 introduces a new syntax for when the result must absolutely be numerical.

#{bar}
	

If the above expression is not a number, an exception is thrown. The purpose of this is to prevent mistakes such as:

The price of the product is #{bar} dollars.
	

and having that resolve to:

The price of the product is foobar dollars.

If, instead, we had written:

The price of the product is ${bar} dollars.
	

The above is obvious nonsense unless the value of bar is numerical. However, with the standard dollar-sign syntax, no such sanity check is performed.

An additional option that you have when using the #{...} syntax is of adding a specifier for the minimum and maximum number of digits to display after the decimal point.

For example, the following says to display the number resulting from the expression foo+bar using a minimum of 2 digits after the decimal point, but not more than 4 digits.

#{foo + bar ; m2M4}
	

(Word to the wise: In later releases, there will be full support for internationalized/localized display of numbers and currencies, so the above is really a stopgap measure in this release.)

In either case, this escape sequence means "print the variable's value here". An expression that has no referent, or whose referent is null, produces no output. Expressions inside template tags don't have these delimiters:

<if foo>
    hello
</if>
	

This prints "hello" if the boolean value of foo is true. In templates, undefined, null, and empty values evaluate to false; all other values evaluate to true. Undefined, null, and empty values are considered to be equal.

Hash access operators

If two identifiers are separated by a dot, the one on the left is a hash (also called "map" or "dictionary" in other languages) the one on the right is the name of a key in that hash:

<p>First Name: ${book.author.firstName}</p>
	

When an identifier followed by an expression in brackets, the expression is evaluated at run time as the name of a hash key. The following are all equivalent, if propName equals "bar" and propStart equals "ba":

foo.bar
foo["bar"]
foo[propName]
foo["ba" + "r"]
foo[propStart + "r"]
	

You can chain together dynamic hash keys. All of the following are equivalent:

foo.bar.baz.bing
foo["bar"]["baz"]["bing"]
foo["bar"].baz["bing"]
	

Sequence access operators

On an expression that evaluates to a TemplateSequenceModel, you can use numerical indexes to access the sequence elements, like this:

mySequence[1]
mySequence[index]
	

Where index is a TemplateModel with a numerical value (eg, 1). Note that in FreeMarker, sequences start at zero.

You can also express subsequences using the range expressions in the form sequence[startIndex..endIndex] like in these examples:

mySequence[2..5]
mySequence[ofs..(ofs+len)]
	

The range expressions are also used to express substrings, like in:

myString[2..5]
	

If the expression to which the range operator is applied can be interpreted both as a sequence and as a string (that is, it evaluates to what we call a multimodel), the subsequence takes precedence over the substring functionality. To access the substring functionality in this case, use this little workaround that will convert the expression into a simple string first, then apply the range operator:

("" + myStringAndSequenceMultiModel)[2..5]
	

Additional operators

In addition to the dot and bracket operators, the following operators are supported in expressions:

Operator Usage Meaning
! !exp Logical not
+ exp + exp String concatenation, or addition in the event that both expressions are numerical.
== exp == exp Equality (string or numeric comparison)
!= exp != exp Inquality (string or numeric comparison)
&& exp && exp Logical and
|| exp || exp Logical or

Operations on numbers

For numerical values, the basic 4-function calculator arithmetic is supported as well as comparisons.

Operator Usage Meaning
+ exp + exp Addition
- exp - exp Subtraction
* exp * exp Multiplication
/ exp / exp Division
% exp % exp modulus (remainder from integer division)
> (or \gt) (exp > exp) greater than
< (or \lt) exp < exp less than
>= (or \gte) (exp >= exp) greater than or equals
<= (or \lte) exp <= exp less than or equals

Note that, for certain comparisons, you have a choice between the "natural" operator and an alternative. You can use either < or \lt. This is because the use of < and > can confuse many HTML-oriented editors and parsers. (Though outputting HTML is not the only use for FreeMarker, in practice, it is probably used mostly for web-based applications.)

One detail you might note in the above is an inconsistency between > and >= and the other operators. An expression containing > or >= must be within parentheses, while this is not required for the other operators. Here is the explanation. Consider the following code:

<if x>y>
	

FreeMarker will not parse this as you intended, because the > is being used to indicate the end of the directive. In other words, <if x> is a valid "if" directive on its own. That is why, if you use the "natural" greater-than operator in a boolean expression, it must be within parentheses. Thus, the above expression must be written as:

<if (x>y)>
	

This is not necessary if you use the "web-safe" alternatives \gt and \gte since then the confusion is not there. Nor are the parentheses necessary if you < or == etcetera.

So you can perfectly well write:

<if x&lt;y>
	

Literals

String literals are delimited by double quotes. A backslash in a string literal can be used to escape a double quote. To include a backslash character, use \\. Operators have standard precedence, and you can use nested parentheses.

Number literals are either positive or negative integers or fractional numbers using the decimal notation.

Method calls

An expression followed by a pair of parentheses with an optional comma separated list of arguments is a method call:

foo()
foo("hello")
deal(king, queen, spade)
	

A method, which is a TemplateMethodModel, can return a list, a hash, a scalar, another method, or null. You can chain together method calls if each one returns a hash containing the next method:

foo().bar()
	

or even if it returns another TemplateMethodModel:

foo()("arg")
	

In the first example, foo() returns a hash in which the key bar's value is a method object that executes bar(). In the second example, it returns a method object that is immediately invoked with argument "arg".

Comments

A comment looks like this:

<comment>
    Comment text...
</comment>
	

Any text or markup inside the comment is ignored. Comments cannot be nested inside other comments.

Here are some more examples of syntactically valid expressions:

!(color == "blue" || color == "violet")
"customer" + customer.number
foo && (!(bar || baz) || bing)
eventManager.getEvent(eventID).importance
	

If you use a boolean expression for its string value (not something you'll often need to do), its string value is "true" if it evaluates to true, otherwise null.