FreeMarker (Templating) API

Each page and component content type in CrafterCMS generally has it’s own view. Crafter Engine, which is in charge of rendering this views, uses Freemarker as the template engine to generate the HTML returned to the client. Documentation for Freemarker can be found at http://freemarker.org.

The most important variable available in the page and component Freemarker templates is the contentModel. Through the contentModel you have access to the content itself. So if in the page you defined a variable name title, you can get the value of title with ${contentModel.title}. Or if you defined a repeater named links, and under it url fields, then accessing the url links is just a matter of iterating the list using <#list contentModel.links.url as url>. The type of the contentModel is SiteItem, so you can also call the methods of that class if the nested property access described previously is not enough, or if you need to access other properties like the storeUrl.

Crafter Engine also populates templates with other useful variables, described below.

Name

Description

Type

siteItemService

Allows access to the site content.

SiteItemService

urlTransformationService

Service for transforming URLs, like transforming the content URL of a page to the web or render URL.

UrlTransformationService

applicationContext

Provides access to the Crafter Engine’s Spring beans and site beans defined in config/spring/application-context.xml.

ApplicationContextAccessor

globalProperties

Provides access to global configuration properties defined in server-config.properties.

PropertySourcesPropertyResolver

navBreadcrumbBuilder

Helper class that returns the list of path components in an URL, to create navigation breadcrumbs.

BreadcrumbBuilder

navTreeBuilder

Helper class that creates navigation trees to facilitate rendering.

NavTreeBuilder

tenantsResolver

Can be used to retrieve the Profile tenants associated to the current site.

TenantsResolver

modePreview

Can be used to check whether Engine is being executed in preview mode (also the value of the crafter.engine.preview property) e.g.

<#if modePreview>
    <!-- Preview-only markup or logic -->
</#if>

Boolean

crafterEnv

Indicates the value of the crafter.engine.environment property

String

siteConfig

The current site Configuration loaded from /config/site.xml.

See XMLConfiguration under org.apache.commons.configuration2 in the Apache Commons apidocs

siteContext

The current SiteContext

ServletContextHashModel

request

The current request

HttpRequestHashModel

requestParameters

The parameter values for the current request

HttpRequestParametersHashModel

cookies

The cookie values for the current request

See Map under the java.util package of the java.base module in the Java documentation

session

The current session

HttpSessionHashModel

locale

The current locale for the current user

See Locale under the java.util package of the java.base module in the Java documentation

authToken

The current authentication (if the user has logged in), created by Spring Security

See Authentication under org.springframework.security.core in the Spring Security apidocs

The following variables are provided for backward compatibility when using Crafter Profile, should be replaced with authToken if possible:

Name

Description

Type

authentication

The current authentication (if the user has logged in), created by the Crafter Security Provider

Authentication

profile

The current profile (if the user has logged in), created by the Crafter Security Provider

Profile

Note

The variables profile and authentication listed above will be null in most cases and should not be used anymore

The following variables are restricted by default, to use them see Configure Custom Services

Name

Description

Type

application

The servlet context

ServletContextHashModel

siteContext

The current SiteContext

SiteContext

Rendering Components

Crafter Engine provides the renderComponent macro that can be used to render components in any template:

Render a Component by Referencing the Path

Using the RenderComponent Macro to Render a component by referencing the path
<!-- Render a component by referencing the path -->
<@renderComponent componentPath='/site/components/headers/header.xml' />

Render a Component by Referencing a Shared Component

Using the RenderComponent Macro to Render a component by referencing a shared component
<!-- Render a component by referencing a shared component from the current item -->
<@renderComponent component=contentModel.mySharedComponent_o.item  />

Render a Component by Referencing an Embedded Component

Using the RenderComponent Macro to Render a component by referencing an embedded component
<!-- Render a component by referencing an embedded component from the current item -->
<@renderComponent component=contentModel.myEmbeddedComponent_o.item />

Render an Embedded Component from Another Component

Using the RenderComponent Macro to Render an Embedded Component from Another Component
<!-- Render an embedded component from another component instead of the current item -->
<#assign sharedItem = siteItemService.getSiteItem('/site/components/global.xml')/>
<@renderComponent parent=sharedItem component=sharedItem.myEmbeddedComponent_o.item />

Render a Component Passing Additional Variables (parameters)

Using the RenderComponent Macro Render a Component Passing Additional Variables
<!-- Render a component passing additional variables -->
<!-- Inside the component's template 'theme' will be available as a global variable -->
<@renderComponent component=contentModel.myComponent.item additionalModel={ 'theme': contentModel.theme_s } />

where:

  • componentPath: a path for a shared component in the site

  • component: a XML node from a node selector field, supports both shared and embedded components

  • parent: the SiteItem to use as a parent in the case of embedded components (defaults to the current item being rendered)

  • additionalModel: a Freemarker hash containing key-value pairs that can be used as global variables in the component’s template

Rendering Navigation

Crafter Engine provides the option of rendering automatically the navigation for you, just by using the macro navigation

See navigation for more information on the macro

Rendering Breadcrumbs

Crafter also offers a renderBreadcrumb macro to easily generate a dynamic list with all the parent pages of a specific url.

See breadcrumb for more information on the macro

Running Scripts/Controllers

Crafter Engine allows executing scripts/controllers from inside Freemarker templates by using the tag @controller. It requires a single parameter, path, which is the path of the script/controller in the site:

Running Scripts/Controllers from inside Freemarker templates
<@controller path=“/scripts/plugins/MyPlugin/1/get-tweets.groovy” />
<@controller path=“/scripts/plugins/MyPlugin/1/get-fbs.groovy” />

Escaping HTML and Scripts

To escape HTML and scripts and prevent their execution in your template, simply wrap the HTML/script to be escaped with the outputformat Freemarker directive set to html:

Escaping HTML and Scripts in Templates
<#outputformat "HTML">
...
</#outputformat>

Keeping Templates Simple

You can access all Crafter Engine services directly from the Freemarker templates as described in the previous sections, however it is a good practice to keep logic and complex operations outside of the templates to simplify debugging and maintenance. An easy way to extract logic from the templates is using Groovy’s closures:

Page or Component Script
 1// Add a closure to the templateModel map, in this case it will find if a page has a custom
 2// nav icon defined in the xml descriptor.
 3
 4templateModel.getNavIcon = { item ->
 5  def storeUrl = urlTransformationService.transform("renderUrlToStoreUrl", item.url)
 6  def siteItem = siteItemService.getSiteItem(storeUrl)
 7  if(siteItem) {
 8    def navIcon = siteItem.navIcon?.text
 9    if(navIcon) {
10      return navIcon
11    }
12  }
13  return "fa-file-o"
14}
Page or Component Template
1<!-- Now the closure is available to use in the template, you only have to use the same name
2     from the script and use the `call` method. -->
3
4<i class="fa ${getNavIcon.call(navItem)}">

If you have a large amount of closures or operations that need to be shared between multiple templates then you should consider creating a Groovy class instead:

Custom Service Class
 1// Define a class with all the logic
 2
 3package org.site.service
 4
 5class NavIconService {
 6
 7  def urlTransformationService
 8  def siteItemService
 9  def defaultIcon
10
11  def getNavItem(item) {
12    ...
13    return this.defaultIcon
14  }
15
16}
Engine Site Application Context file - application-context.xml
1<!-- Add a bean definition using the new class -->
2
3<bean id="navIconService" class="org.site.service.NavIconService">
4  <property name="urlTransformationService" ref="crafter.urlTransformationService"/>
5  <property name="siteItemService" ref="crafter.siteItemService"/>
6  <property name="defaultIcon" value="${nav.defaultIcon}"/>
7</bean>
Engine Site Configuration file - site-config.xml
 1<!-- If needed the bean can use external configuration for easy management -->
 2
 3<?xml version="1.0" encoding="UTF-8"?>
 4<site>
 5  ...
 6  <nav>
 7    <defaultIcon>fa-file-o</defaultIcon>
 8  </nav>
 9  ...
10</site>
Template
1<!-- Now the bean can be use just like Crafter built-in services -->
2
3<i class="fa ${navIconService.getNavIcon(navItem)}">

Note

All beans defined in the Engine Site Application Context file will be available in templates.

For more information on Crafter Engine Site configuration files, see Project-level/Site-level Configuration Files