The format of interpolations is
${expression}
, where
expression
can be all
kind of expression (e.g. ${100 + x}
).
The interpolation is used to insert the value of the
expression
converted to
text (to string). Interpolations can be used only on two places: in
text sections (e.g.,
<h1>Hello ${name}!</h1>
) and in string literal
expressions (e.g., <#include
"/footer/${company}.html">
).
A frequent mistake of users is the usage of interpolations in
places where they needn't/shouldn't/can't be used. Interpolations
work only in text sections (e.g.
<h1>Hello ${name}!</h1>
) and in string literals
(e.g. <#include
"/footer/${company}.html">
). A typical
WRONG usage is <#if
${big}>...</#if>
, which will give syntactical
error. You should simply write <#if
big>...</#if>
. Also, <#if
"${big}">...</#if>
is WRONG,
since it converts the parameter value to string and the
if
directive wants a boolean value, so it will
cause a runtime error.
The result of the expression must be a string, number or date/time/date-time value. This is because only numbers and date/time/date-time values are converted to string by interpolation automatically, values of other types (such as booleans, sequences) must be converted to string "manually" somehow (see some advices later), or an error will stop the template processing.
Guide for inserting strings; don't forget escaping!
If the interpolation is in a text section (i.e., not in a string literal
expression), the string that it will insert will be
automatically escaped if an escape
directive is in effect. If you are generating HTML it's
strongly recommended to utilize this to prevent cross-site-scripting
attacks and not-well-formed HTML pages. Here's a quick
example:
<#escape x as x?html> ... <p>Title: ${book.title}</p> <p>Description: <#noescape>${book.description}</#noescape></p> <h2>Comments:</h2> <#list comments as comment> <div class="comment"> ${comment} </div> </#list> ... </#escape>
This example shows that when generating HTML you better put
the whole template inside the escape
directive.
Thus, if the book.title
contains
&
, it will be replaced with
&
in the output so the page remains
well-formed HTML. If a user comment contains tags like
<iframe>
(or any other element), they will
become to <iframe>
and like,
rendering them harmless. But sometimes you really have HTML in the
data-model, like let's assume book.description
above is stored as HTML in the database, in which case you have to
neutralize the enclosing escape
with a
noescape
. Without the enclosing
escape
, the template would look like:
... <p>Title: ${book.title?html}</p> <p>Description: ${book.description}</p> <h2>Comments:</h2> <#list comments as comment> <div class="comment"> ${comment?html} </div> </#list> ...
This does the same as the earlier example, but here you may
forget some ?html
-s, which is a security risk. In
the earlier example you may forget some
noescape
-s, which gives bad output too, but it's
at least no a security risk.
Guide for inserting numerical values
If the expression evaluates to a number then the numerical
value will be converted to string according the default number
format. This may includes the maximum number of decimals, grouping,
and like. Usually the programmer should set the default number
format; the template author don't have to deal with it (but he can
with the number_format
setting; see in the documentation of
setting
directive). Also, you can override
the default number format for a single interpolation with the string
built-in.
The decimal separator used (and other such symbols, like the group separator) depends on the current locale (language, country), that also should be set by the programmer. For example, this template:
${1.5}
will print something like this if the current locale is English:
1.5
but if the current locale is German then it will print something like:
1,5
since German people use comma as decimal separator.
As you can see, interpolations print for human audience (by
default at least), as opposed to ''computer audience''. In some
cases this is not good, like when you print a database record ID
as the part of an URL or as an invisible field value in a HTML
form, or when you print CSS/JavaScript numerical literals, because
these printed values will be read by computer programs and not by
humans. Most computer programs are very particular about the
format of the numbers, and understand only a kind of simple US
number formatting. For that, use the c
(stands for
''computer audience'') built-in, for example:
<a href="/shop/productdetails?id=${product.id?c}">Details...</a>
Guide for inserting date/time/date-time values
If the expression evaluates to a date-like value then that
will be transformed to a text according to a default format. Usually
the programmer should set the default format; you don't have to deal
with it (but if you care, see the
date_format
, time_format
and
datetime_format
settings in the
documentation of the setting
directive). Also, you can override the default formatting for
a single interpolation with the string
built-in.
To display a date-like value as text, FreeMarker must know
which parts of it are in use, that is, if only the date part
(year, month, day), or only the time part (hour, minute, second,
millisecond), or both. Unfortunately, because of the technical
limitations of Java platform, for some variables it is not
possible to detect this automatically; ask the programmer if the
data-model contains such problematic variables. When it's not
possible to find out which parts of the date are in use, then you
must help FreeMarker with the date
,
time
and datetime
built-ins (like ${lastUpdated?datetime}
), or it
will stop with error.
Guide for inserting boolean values
By default an attempt to print boolean values with
interpolation causes an error and aborts template processing. For
example this will cause an error: ${a == 2}
and
will not print ''true'' or something like that. That's because
there's no universally useful way of representing booleans
(sometimes you want to print yes/no, sometimes enabled/disabled,
on/off, etc.).
However, you can convert booleans to strings with the ?string
built-in. For example, to print the value of the "married"
variable (assuming it's a boolean), you could write
${married?string("yes", "no")}
.
FreeMarker can be configured with a default boolean format
with the boolean_format
setting, then
${married}
and such will work. However, in most
applications it's not recommended, as boolean should be rendered
differently on different places, and leaving the formatting on the
default is possibly just an oversight and thus should generate
error.
When you want to generate JavaScript or other computer
language parts, then ${someBoolean?c}
("c" stands for computer audience) should be used to
print true/false. (Remember that ?c
was also used
to print numbers for computer audience.)
The exact conversion rules
For those who are interested, the exact rules of conversion from the expression value to string (which is then still subject to escaping) are these, in this order:
-
If the value is a number, then it is converted to string in the format specified with the
number_format
setting. So this usually formats for human audience, as opposed to computer audience. -
Else if the value is date, time or date-time, then it is converted to string in the format specified with the
date_format
,time_format
ordatetime_format
setting, respectively. If it can't be detected what kind of date-like value it is (date vs time vs date-time), an error will occur. -
Else if the value is a string, then there is no conversion.
-
Else if the engine is in classic compatibility mode:
-
If the value is a boolean, true values are converted to "true", false values are converted to an empty string.
-
If the expression is undefined (
null
or a variable is undefined), it is converted to an empty string. -
Else an error will abort the template processing.
-
-
Else an error will abort the template processing.