The template at a glance

Page Contents

The simplest template is a plain HTML file (or whatever text file -- FreeMarker is not confined to HTML). When the client visits that page, FreeMarker will send that HTML to the client as is. However if you want that page to be more dynamic then you begin to put special parts into the HTML which will be understood by FreeMarker:

Anything not an FTL tag or an interpolation or comment is considered as static text, and will not be interpreted by FreeMarker; it is just printed to the output as is.

With FTL tags you refer to so-called directives. This is the same kind of relationship as between HTML tags (e.g.: <table> and </table>) and HTML elements (e.g., the table element) to which you refer to with the HTML tags. (If you don't feel this difference then just take "FTL tag" and "directive" as synonyms.)

Examples of directives

Though FreeMarker has far more directives, in this quick overview we will only look at three of the most commonly used ones.

The if directive

With the if directive you can conditionally skip a section of the template. For example, assume that in the very first example you want to greet your boss, Big Joe, differently from other users:

<html>
<head>
  <title>Welcome!</title>
</head>
<body>
  <h1>
    Welcome ${user}<#if user == "Big Joe">, our beloved leader</#if>!
  </h1>
  <p>Our latest product:
  <a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>  

Here you have told FreeMarker that the '', our beloved leader'' should be there only if the value of the variable user is equal to the string "Big Joe". In general, things between <#if condition> and </#if> tags are skipped if condition is false (the boolean value).

Let's detail the condition used here: The == is an operator that tests if the values at its left and right side are equivalent, and the results is a boolean value, true or false accordingly. On the left side of == I have referenced a variable with the syntax that should be already familiar; this will be replaced with the value of the variable. In general, unquoted words inside directives or interpolations are treated as references to variables. On the right side I have specified a literal string. Literal strings in templates must always be put inside quotation marks.

This will print "Pythons are free today!" if their price is 0:

<#if animals.python.price == 0>
  Pythons are free today!
</#if>  

Similarly as earlier when a string was specified directly, here a number is specified directly (0). Note that the number is not quoted. If you quoted it ("0"), FreeMarker were misinterpret it as a string literal.

This will print "Pythons are not free today!" if their price is not 0:

<#if animals.python.price != 0>
  Pythons are not free today!
</#if>  

As you may have guessed, != means not equivalent.

You can write things like this too (using the data-model used to demonstrate hashes):

<#if animals.python.price < animals.elephant.price>
  Pythons are cheaper than elephants today.
</#if>  

With the <#else> tag you can specify what to do if the condition is false. For example:

<#if animals.python.price < animals.elephant.price>
  Pythons are cheaper than elephants today.
<#else>
  Pythons are not cheaper than elephants today.
</#if>  

This prints ''Pythons are cheaper than elephants today.'' if the price of python is less than the price of elephant, or else it prints ''Pythons are not cheaper than elephants today.''

If you have a variable with boolean value (a true/false thing) then you can use it directly as the condition of if:

<#if animals.python.protected>
  Warning! Pythons are protected animals!
</#if>  

The list directive

This is useful when you want to list something. For example if you merge this template with the data-model I used earlier to demonstrate sequences:

<p>We have these animals:
<table border=1>
  <tr><th>Name<th>Price
  <#list animals as being>
  <tr><td>${being.name}<td>${being.price} Euros
  </#list>
</table>  

then the output will be:

<p>We have these animals:
<table border=1>
  <tr><th>Name<th>Price
  <tr><td>mouse<td>50 Euros
  <tr><td>elephant<td>5000 Euros
  <tr><td>python<td>4999 Euros
</table>  

The generic format of the list directive is:

<#list sequence as loopVariable>repeatThis</#list>

The repeatThis part will be repeated for each item in the sequence that you have given with sequence, one after the other, starting from the first item. In all repetitions loopVariable will hold the value of the current item. This variable exists only between the <#list ...> and </#list> tags.

As another example, we list the fruits of that example data model:

<p>And BTW we have these fruits:
<ul>
<#list whatnot.fruits as fruit>
 <li>${fruit}
</#list>
<ul>  

The whatnot.fruits expression should be familiar to you; it references a variable in the data-model.

The include directive

With the include directive you can insert the content of another file into the template.

Suppose you have to show the same copyright notice on several pages. You can create a file that contains the copyright notice only, and insert that file everywhere where you need that copyright notice. Say, you store this copyright notice in copyright_footer.html:

<hr>
<i>
Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
<br>
All Rights Reserved.
</i>  

Whenever you need that file you simply insert it with the include directive:

<html>
<head>
  <title>Test page</title>
</head>
<body>
  <h1>Test page</h1>
  <p>Blah blah...
<#include "/copyright_footer.html">
</body>
</html>  

and the output will be:

<html>
<head>
  <title>Test page</title>
</head>
<body>
  <h1>Test page</h1>
  <p>Blah blah...
<hr>
<i>
Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
<br>
All Rights Reserved.
</i>
</body>
</html>  

If you change the copyright_footer.html, then the visitor will see the new copyright notice on all pages.

Using directives together

You can use directives as many times on a page as you want, and you can nest directives into each other similarly as you can nest HTML elements into each other. For example this will list the animals and print the name of large animals with bigger font:

<p>We have these animals:
<table border=1>
  <tr><th>Name<th>Price
  <#list animals as being>
  <tr>
    <td>
      <#if being.size == "large"><font size="+1"></#if>
      ${being.name}
      <#if being.size == "large"></font></#if>
    <td>${being.price} Euros
  </#list>
</table>  

Note that since FreeMarker does not interpret text outside FTL tags, interpolations and comments, it doesn't see the above font tags as badly nested ones.

Dealing with missing variables

In practice the data-model often has variables that are optional (i.e., sometimes missing). To spot some typical human mistakes, FreeMarker doesn't tolerate the referring to missing variables unless you tell them explicitly what to do if the variable is missing. Here we will show the two most typical ways of doing that.

Note for programmers: A non-existent variable and a variable with null value is the same for FreeMarker, so the "missing" term used here covers both cases.

Wherever you refer to a variable, you can specify a default value for the case the variable is missing, by following the variable name with a ! and the default value. Like in the following example, when user is missing from data model, the template will behave like if user's value were the string "Anonymous". (When user isn't missing, this template behaves exactly like if !"Anonymous" were not there):

<h1>Welcome ${user!"Anonymous"}!</h1>  

You can ask whether a variable isn't missing by putting ?? after its name. Combining this with the already introduced if directive you can skip the whole greeting if the user variable is missing:

<#if user??><h1>Welcome ${user}!</h1></#if>  

Regarding variable accessing with multiple steps, like animals.python.price, writing animals.python.price!0 is correct only if animals.python is never missing and only the last subvariable, price, is possibly missing (in which case here we assume it's 0). If animals or python is missing, the template processing will stop with an "undefined variable" error. To prevent that, you have to write (animals.python.price)!0. In that case the expression will be 0 even if animals or python is missing. Same logic goes for ??; animals.python.price?? versus (animals.python.price)??.

FreeMarker Manual -- For FreeMarker 2.3.20
HTML generated: 2013-06-27 20:54:33 GMT
Edited with XMLMind XML Editor
Here!