Freemarker Tips and Tricks
- Declaring the Titania Delivery Tag Library
-
In order to use the Titania Tag Library, the following must be included at the top of the template.
<#assign td=JspTaglibs['http://www.titaniasoftware.com/harp/taglib']/>
- Includes
-
Freemarker allows for the modular development of HTML pages. Smaller templates can be combined together to make a full page. To include one template in another, add the following to the destination template, wherever you want the target template to be included:
<#include "path/to/template.ftl" />
- Page Variables
-
Titania Delivery populates the templates with a model consisting of many variables. These variables can be accessed via:
${propertyName.fieldName}
- Escapes
-
It is strongly advised to escape the text received from a data model. Freemarker provides a number of built-in functions to accomplish this. This allows Freemarker to format text in a manner that the destination is expecting. For example, it can escape special characters for insertion into the html page, or format a String so that it can be used as a JavaScript variable. To escape data that will be output directly to a page, use:
${propertyName.fieldName?html}
To escape data passed into JavaScript strings, use:
${propertyName.fieldName?js_string}
For example:
<script> var portalTitle = "${portal.title?js_string}"; </script>
- Comments
-
You can mark comments in your template that will not be rendered to the HTML using:
<#--
and-->
.<#-- This is a comment. -->
- Conditional Processing
-
Freemarker supports conditional processing via the
<#if>
,<#else>
, and<#elseif>
expressions.<#if condition1> ... <#elseif condition2> ... <#else> ... </#if>
- Loops
-
You can iterate over arrays of values using
<#list>
.<ul> <#list array as value> <li>${value_index} - ${value?html}</li> </#list> </ul>
When iterating through a list, a number of special values become available.
${item_index}
- The numerical index within the array of the current entry.
${item_has_next}
- A boolean value indicating whether there is another value in the list.
- Data Existence
-
It is sometimes the case that a data model may or may not exist on a page. In these instances, the template must check for their existence before referencing them. This can be accomplished via:
${propertyName.fieldName??}
which returns a boolean value. For example:
<#if modelName.fieldName??> ${propertyName.fieldName?html} <#else> <b>No Value!</b> </#if>
Important: If a Freemarker template attempts to reference a field that is not present, an error message will be rendered at the location of the error, and further rendering will halt, resulting in a broken page. You should always check for the existence of optional properties before attempting to render them. - Default Values
-
In cases where a default value is available, you can avoid using
<#if>
by using the default value operator (!).${propertyName.optionalProperty!"Default Value"}
- Attempt/Recover
-
Often, if there is an error in a template, the page can fail to render entirely, without an error message that could help track down the error. You can alleviate this problem by wrapping part of a template, or even the whole template, in an
<#attempt>
block, using<#recover>
to report any errors.<#attempt> <#-- code here --> <#recover> ERROR: <pre>${.error?html}</pre> </#attempt>
If a Freemarker error occurs inside the
<#attempt>
block, the code after the<#recover>
tag will be executed instead, and you can access the error via the.error
variable. - Assigning Custom Model Properties
-
Freemarker templates can declare custom properties using the
<#assign>
directive. For example:<#assign customProperty="some value"/>
Or
<#assign customMarkupSnippet> <p>Markup Snippet</p> </#assign>
You can then use the custom model property the same way as you would any other. With the above declarations, this template:
<p>Custom property: ${customProperty?html}</p> ${customMarkupSnippet}
would result in the following markup:
<p>Custom property: some value</p> <p>Markup Snippet</p>
- Passing Parameters to Included Modules
-
The properties declared using
<#assign>
are made available for the rest of the page, and remain in effect when processing template language referenced via<#include>
. You can use this fact to parameterize behavior in reused template modules. For example, you could have the following in a reused module:<#-- If trigger is defined and true --> <#if trigger?? && trigger> Optional Stuff </#if>
In a template using this module, you could assign 'trigger' to true to enable the optional behavior.
<#assign trigger=true> <#include "otherModule.ftl"/>
- Macros
-
Freemarker allows for creating additional user-defined directives called macros; essentially a reusable template fragment assigned to a variable. For instance, the following macro could be defined:
<#macro greet> <#if user??> <p>Hello, ${user.userName}</p> <#else> <p>Hello, Titania Delivery</p> </#if> </#macro>
Later in the template (or in any template that includes a template with the above macro definition), the following could be used to execute the macro:
<@greet/>