Content Application Developer Manual / Version 2406.0
Table Of Contents
A template accesses variables in its current environment that have been provided by the controller.
In a CoreMedia Content Application Engine template, the property
self
has a special meaning: it denotes the
target object on which the template was invoked. It is the equivalent of the
this
object reference in Java methods. A simple FreeMarker template
to display the title
property of a target object of type
com.company.Article
and set the Content-Type
HTTP response header
looks as follows:
<@cm.responseHeader name="Content-Type" value="text/html; charset=UTF-8"/> <#-- @ftlvariable name="self" type="com.company.Article" --> ${self.title}
While the @ftlvariable
comment is not necessary, it serves as a hint for the
IntelliJ IDEA development environment to support code completion for the self
variable.
Template Output Escaping for HTML
To prevent output that allows cross-site scripting (XSS) attacks, the CAE switches on HTML escaping for all FreeMarker templates. The default output format for all templates is set to HTML. See FreeMarker online documentation for details.
In special cases, it might be necessary to disable escaping. For this purpose, FreeMarker provides the directive
<#noautoesc/>
or built-in for Strings ?no_esc
.
Caution
Note that disabling HTML escaping can lead to cross-site scripting (XSS) vulnerabilities if a templates outputs unchecked data like user input that may contain scripts.
Template Inclusion
Other templates can be included via FreeMarker's <#include>
directive. However, in this
case the view dispatcher is not involved in determining the included file. In order to involve
the view dispatcher, you need to use the include
macro from the
Content Application Engine's FreeMarker library
cae.ftl
. This library is auto-imported under the namespace cm
.
In FreeMarker, custom macros are invoked using <@namespace.macro>
.
The macro @cm.include
requires an attribute self
to determine the
target object for the view. The following code will find the appropriate template named "teaser"
for anObject
and include its output into the current page. Inside that template,
self
is temporarily bound to anObject
:
<@cm.include self=anObject view="teaser"/>
Assuming that anObject
is of type Article, the template
Article.teaser.ftl
will be included. The view attribute is
optional; the default template (in this example, Article.ftl
) will be chosen in
case it is omitted. When no template for the view name "teaser" is found, the search will end
with a failure - the default template is not used as a
fallback! Also, the include will fail if anObject
is null
(unless you specify a default value of cm.UNDEFINED
for self
, see reference).
A template including the teaser views of all objects in its
articles property would look as follows. Within each teaser
template, self
will be bound to the respective article
object.
Note the use of FreeMarker's built-in #list
directive:
<#list self.articles as article> <@cm.include self=article view="teaser"/> </#list>
When looking for the appropriate template, the Content Application Engine performs the same steps as in an object-oriented language. If no template is defined for a target bean type, it will be inherited from its super type: the CAE will look for the template upwards in the inheritance hierarchy. It also considers interfaces, so you can register templates for interfaces, too.
Rendering Markup
Markup properties are also rendered by including them. Assuming self
has a method
getText
returning
a com.coremedia.xml.Markup,
this template snippet will render the text value using the default markup view.
<@cm.include self=self.text/>
The CoreMedia CAE defines a default view for objects of type com.coremedia.xml.Markup that converts CoreMedia richtext to XHTML. See Section 4.3.4.1, “Rendering Markup” for details.
Template Parameters
CAE includes allow handing over parameters from the calling template to the included one. This is implemented by temporarily setting a request scope attribute and resetting it to its old value after the included fragment returns.
In a FreeMarker template, the include
macro and the getLink
function
support such parameters by using a hash-valued parameter named params
.
<@cm.include self=article view="teaser" params={ "images": false }/>
Within the "teaser" template, the variable images
will
be set to false
and will revert to its original value (if any) afterwards.
Linking
Like include, linking also works with objects.
To compute a URL to an object and a view, you can use the CAE FreeMarker library function getLink()
:
<a href="${cm.getLink(article, "teaser")}">more</a>
This function consults the LinkFormatter strategy to compute a URL and hands in its first parameter as the target object and its second parameter as the (optional) view identifier. The link formatter strategy requires a link scheme that is able to handle the class of the object. All generated content beans implement the ContentBean interface for which a link scheme exists; so there is no need to implement another one. It is necessary for beans that originate from other sources.
Using the function in an expression (FreeMarker: "interpolation"), the formatted URL is written directly to the page.
If the URL is used several times within the template or if you feel that the actual template code looks
cleaner when separating URL computation and usage, use FreeMarker's #assign
directive to assign
the resulting URL to a variable:
<#assign teaserLink=cm.getLink(article, "teaser") /> <a href="${teaserLink}">more</a>
You can hand over parameters to the LinkFormatter
as an optional third parameter of the
getLink()
function, specified as a FreeMarker hash of name-value pairs.
If you do not want to specify a view, you can also hand over parameters as the second parameter.
Do not forget to quote the keys and not quote the values
(unless they are strings, of course).