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 by default. More precisely, each FreeMarker template is automatically wrapped in an
#escape
directive:
<#escape x as x?html> ... </#escape>
This #escape
directive leads to all FreeMarker "interpolations" (${...}
expressions)
being HTML-escaped when written to the output stream. All literal output of the template is of course
not escaped. See FreeMarker online documentation for details.
In special cases, it might be necessary to disable escaping. For this purpose, FreeMarker provides the directive
#noescape
. However, this directive is only allowed nested inside an #escape
directive,
so because the outer #escape
directive is implicit, an IDE could regard this an error.
To always have valid templates and to also be able to change the escaping type to something other than HTML,
the CAE only wraps templates that do not contain any #escape
directives themselves.
Thus, to switch off escaping, you have to make the outer escaping explicit:
<#escape x as x?html> ... <#noescape>...</#noescape> ... </#escape>
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. |
The same applies to the use case of changing the escaping type to something other than HTML:
<#escape x as x?xml> ... </#escape>
Like said above, specifying any #escape
directive in your template completely disables
any automatic escaping normally added by the CAE. Otherwise, specifying custom escaping would have
lead to double escaping, which is not desired.
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
.
Macro include
also allows adding parameters as
additional attribute-value pairs to the macro itself. These two includes are equivalent:
<@cm.include self=article view="teaser" params={ "images": false }/> <@cm.include self=article view="teaser" 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><@cae.link target=article view="teaser"/></#assign> <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).