Magnolia 4.5 reached end of life on June 30, 2016. This branch is no longer supported, see End-of-life policy.

Page tree
Skip to end of metadata
Go to start of metadata

Magnolia Templating Samples module is a showcase of Magnolia templating features for developers. It contains customizable examples of dialogs, page and component templates, and servlets. The examples demonstrate how to write the same action in Freemarker and JSP and introduce the tag libraries.

Download

Templating Samples is available in the add-ons folder of both the Enterprise and Community Edition bundles. You can also download it from the Magnolia Store or Nexus repository.

Installing

Templating Samples is a community module. It is not typically installed. Go to Magnolia Store > Installed modules in AdminCentral to check. To install the module individually, see the general module installation instructions.

Uninstalling

See the general module uninstalling instructions and advice.

Configuration

Shortcuts to the module configuration are in the Samples > Configuration menu in AdminCentral.

Overview of samples

The module demonstrates how to customize the following page elements and components:

  1. Dialogs are used to edit page properties and component content.
  2. Page templates render pages, area and component content.
  3. Area templates render area and component content.
  4. Component templates render components that users edit.
  5. Servlets process data and provide dynamic content.

There are a number of toolbars on each page:

  • The page toolbar at the top of the page allows editors to edit page specific properties, to view the page in preview mode and to access AdminCentral.
  • Each page area has a toolbar and when clicked the focus shifts to the area: the component toolbars in the area appear and the other area toolbars disappear.
  • The component toolbar contains function icons that typically allow editors to edit, move and delete content.

Dialogs

The authoring system uses Dialogs for content contribution and editing. Component dialogs are accessed by clicking edit icon in the toolbars.

The sample dialog definitions are in  /modules/samples/dialogs.

There are six sample dialogs:

Dialogs can be linked to page, area and component definitions and the same dialog can be used reused multiple times. For example the mainProperties dialog is used by the main page definition and the searchResult component definition, and the samplesTextDialog by the linkList and text components definitions.

mainProperties dialog

A properties dialog typically allows for page specific properties such as the title displayed in the browser window and navigation menu, and page meta data such as the page keywords and description. Open any page on demoauthor and click Properties in the top bar to see how the dialog is used in the Standard Templating Kit.

The mainProperties dialog in the Templating Samples module is a simple dialog that you can customize. It contains one tab control , one edit control and one fckEdit control.

To open the dialog, click Properties in the top bar on any page based on the main template, for example the ftl-sample-site or jsp-sample-site page. Change the title and note how the page title, browser window and tab title change dynamically. The title inserted in Website when the page is created is used as the default title property and is rendered by the main page script.

To access the dialog configuration go to Samples > Configuration modules/samples/dialogs/mainProperties. For a list of properties you can use in a dialog definition see Dialogs .

howTo dialog

The howTo dialog is an example of a component dialog. It is referenced in the howTo component definition. The dialog allows the user to enter a title and text, upload an image and select a date from a calendar. The HowTo component script renders the dialog content and some additional content.

To open the dialog, open the ftl-howTo or jsp-howTo page, click the Main toolbar and then the Edit icon in the HowTo component toolbar.

The howTo dialog configuration is in Configuration /modules/samples/dialogs/howTo. The four fields use the edit, fckEdit, file and date controls.

samplesTextDialog

The samplesTextDialog is a simple dialog that contains two fields, title and text. The dialog configuration is in Configuration /modules/samples/dialogs/samplesTextDialog. This configuration is identical to the howTo dialog with the omission of the image and date fields. The dialog is referenced the linkList and text component definitions.

Link dialogs

The externalLinkDialog and internalLinkDialog dialogs demonstrate how input is collected to render external and internal links. The former uses the edit control for the target URL and the latter the link control that allows for the selection of an internal page.

The dialogs are referenced by the externalLink and internalLink component definitions and the content is rendered by the link component script.

The dialogs are configured in Configuration modules/samples/dialogs/externalLinDialog and /internalLinkDialog.

samplesFieldShowRoom dialog

The samplesFieldShowRoom dialog demonstrates numerous input controls available in Magnolia. This dialog is referenced by the fieldShowRoom component.

The component is meant to showcase the dialog tabs and fields, and only renders static content when added to a page. To view the dialog:

  1. On any page based on the main template click the Main toolbar.
  2. Click the Add icon in the New Main Component box.
  3. Select Fields Show Room Component in the selector dialog.
  4. View the various fields and options in the tabs.

Each tab of the dialog shows the many controls available with varying options.

The dialog is configured in Configuration /modules/samples/dialogs/samplesFieldShowRoom and shows sample configurations for most available fields.

Templates

The module includes a number of page, area and component templates written in FreeMarker and JSP. The template definitions are in Configuration modules/samples/templates/pages and /components. Area template definitions are configured in the page template definition.

A template definition makes a template script available to the system by providing a name and common template properties.

A template script renders content. It can be written in FreeMarker, JSP or a custom templating language. The script instructs the renderer where on the page to place content. It contains placeholders for content attributes such as headings and images.

Template definition properties vary from definition to definition, but all have the following required properties:

  • renderType that determines the TemplateRenderer to use.
  • templateScript that defines the URI to the script. For each sample template definition scripts in FreeMarker and JSP are provided.

With the exception of these two properties, the Freemarker and JSP template definitions are identical. Magnolia ships with two renderers FreemarkerRenderer and JspRenderer .

All of the sample FreeMarker and JSP scripts functionally identical. Scripts can also be written in a custom templating language provided that you integrate a renderer for that language into Magnolia.

Editing template scripts

JSP scripts can only reside on the file system. They are extracted onto the file system during module installation or update. To test JSP template scripts and see your changes take effect:

  1. On your files system go to the /<CATALINA_HOME>/webapps/<contextPath>/templates/samples folder. This is typically at <apache-tomcat>/webapps/magnoliaAuthor/templates/samples.
  2. Locate the scr4ipt in one of the sub folders.
  3. Edit the script in a code editor.
  4. Save.

FreeMarker scripts can be loaded from any of the options below and the system searches for them in this order:

  1. Filesystem of the webapp. You can place a script file in the /<CATALINA_HOME>/webapps/<contextPath>/templates folder.
  2. templates workspace. The template needs to be enabled to be considered.
  3. The web application's classpath. The FreeMarker template scripts in the Templating Samples module are packaged inside the module JAR. A module JAR resides in the classpath so the system finds them in the third location.

The easiest way to test FreeMarker scripts is to recreate them in the templates workspace:

  1. Go to Templating Kit > Templates.
  2. Create a new folder samples. This starts a folder hierarchy that matches the template path in the module JAR.
  3. Create the following sub folders under samples: areas, components, includes, macros and pages.
  4. Locate the scripts in the Git repository, download and then copy the code. The scripts are located in folders that match those created in 3. above.
  5. Create a new template under the appropriate folder in Templates and name it so it corresponds with he template you copied.
  6. Click Edit template and paste the content in the dialog.
  7. Check the Enable template box in the dialog.
  8. Save.

Page templates

The module includes two page templates.

  • main renders the FTL and JSP Sample Site pages and all sub pages except the Sample Product Selection pages.
  • mainVirtualURI demonstrates the use of virtual URI mapping and renders the Sample Product Selection pages. When you select a product, the page is reloaded with your selection in the URL.

The template definitions are in Configuration /modules/samples/templates/pages/ftl and /jsp.

The templates are used on pages like this:

Page

Template definition

Template script

ftl-sample-site

pates/ftl/main

main.ftl

jsp-sample-site

pages/jsp/main

main.jsp

ftl-products

pages/ftl/mainVirtualURI

virtualURI.ftl

jsp-products

pages/jsp/mainVirtualURI

virtualURI.jsp

Go to Website in AdminCentral to see how the templates are assigned to pages.

main template

The main page template is a generic template sample that demonstrates multiple elements and functionality.

main page definition

The main page template definitions are in Configuration modules/samples/templates/pages/ftl and /jsp. Like all the sample template definitions the FreeMarker and JSP samples differ only in the renderer set in the renderType property and the template script referenced in the templateScript property.

The main template definition:

  • Uses the SampleTemplate model class referenced in the class node. A model class can be used to extend the default template definition by adding custom properties. A model class provides additional functionality and many templates do not use one.
  • Includes a custom titleSize property that is allowed for by the model class. This property defines the size of the title on the page. The model class reads the titleSize property and makes it available to the template script. The script can then either render the property value on the page or use it in some custom presentation logic. See main page script below.
  • References the mainProperties dialog. Click on Properties in the top bar of any page to see the dialog.
  • Makes the template available for use in Website by setting the visible property to true.

A parameters content node with custom properties under it can be added to the definition as an alternative to using a custom model class, or in addition to using one. Any properties under parameters are available to the template script automatically.

Custom properties are made available to the template script through the def templating support object. See examples in main page script below.

SampleTemplate model class

Model is a Java program that holds your business logic. It can do any task required, such as execute a search or calculate an insurance policy. It holds the results of the logic execution and passes them to a renderer.

The SampleTemplate model class demonstrates how to extend the default template with custom properties. The Java logic makes the titleSize property available to the template script.

public class SampleTemplate extends ConfiguredTemplateDefinition {
    private String titleSize = "1";
    public String getTitleSize() {
        return titleSize;
    }
    public void setTitleSize(String titleSize) {
        this.titleSize = titleSize;
    }

No Java logic is needed to make properties under the parameters content node available. This is default functionality for which you do not need a custom class.

main page script

The main page script renders the main page template. Here are a few coding examples. More examples are provided in Area templates and Component templates discussed later.

Tag libraries

The cms.init tag initializes the tag libraries. Once initialized the toolbars on the author instance render automatically.

FreeMarker

<head>
...       
 [@cms.init /]
...
</head>

In JSP in addition to the cms.init tag, the libraries need to be referenced specifically. Appropriate references should be added to all scripts.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cms" uri="http://magnolia-cms.com/taglib/templating-components/cms"%>
<%@ taglib prefix="cmsfn" uri="http://magnolia-cms.com/taglib/templating-components/cmsfn"%>
....
<head>
....
 <cms:init />
....
</head>

Areas

main script is an inclusive script i.e. it includes all page areas using the cms.area name tag. Each area definition references its own script.

FreeMarker

<div id="header">
  [#-- ****** navigation area ****** --]
  [@cms.area name="navigation" /]
  [#-- ****** stage area ****** --]
  [@cms.area name="stage"/]
</div><!-- end header -->

JSP

<div id="header">
  <!-- ****** navigation ****** -->
  <cms:area name="navigation" />
  <!-- ****** stage area ****** -->
  <cms:area name="stage" />
</div>

Custom properties

The def templating support object provides access to the template definition. The values of custom properties are read using the dot notation: def.<propertyName>

  • The titleSize property is an example of extending the default template definition with a custom property that is allowed by the model class. It defines the size of the main heading on the page. The model class makes the property available to the script.
  • The customProperty property under the parameters content node is an example of automatically extending the default template definition. These properties are available to the template script automatically.

To see how they work amend the main script as shown in the code examples below:

  1. Replace the <h2. tags in the page content area of the script and then change the value of the titleSize property in the template definition to see how page title size can be changed by configuration.
  2. Add the def.customProperty tag.

FreeMarker

[#-- ****** page content ****** --]
<h${def.titleSize!}>${content.title!content.@name}</h${def.titleSize!}>
<p>${def.customProperty!""}</p><br />

For custom properties under the parameters content node of the definition JSP needs the containing parameters node as part of the notation.

<!-- ****** page content ****** -->
<h${def.titleSize}>
  <c:choose>
    ...
</h${def.titleSize}>
<p>${def.parameters.customProperty}</p><br />

Here is the result with the titleSize set to 3.

mainVirtualURI template

mainVirtualURI page definition

The mainVirtualURI template definition is an example of using virtual URI mapping . The page template definitions are in Configuration modules/samples/templates/pages/ftl and /jsp.

Example mappings are configured in Configuration modules/samples/virtualURIMapping/ftl-products and /jsp-products. The RegexpVirtualURIMapping class allows you to specify a pattern that matches a sequence of characters. The regular expression in fromURI maps an incoming request to a page defined in toURI. The user is forwarded to what appears to be sub page of ftl-sample-site/ftl-products and jsp-sample-site/jsp-products but in fact the same page is loaded. The action prefix forward hides the true target and displays the fromURI URL in the browser address bar.

virtualURI page script

The virtualURI page script creates links to products.

In FreeMarker ctx.contextPath gets the context path corresponding to the current request and ctx.parameters.product renders the selection.

<p>Select a product:
    <a href="${ctx.contextPath}${content.@path}/product1">Product 1</a>
    <a href="${ctx.contextPath}${content.@path}/product2">Product 2</a>
    <a href="${ctx.contextPath}${content.@path}/product3">Product 3</a>
</p>
<p>You selected: <b>${ctx.parameters.product!"none yet"}</p>

In JSP pageContext.request.contextPath gets the context path corresponding to the current request and param.product renders the selection.

<p>Select a product:
    <a href="${pageContext.request.contextPath}${content['@path']}/product1">Product 1</a>
    <a href="${pageContext.request.contextPath}${content['@path']}/product2">Product 2</a>
    <a href="${pageContext.request.contextPath}${content['@path']}/product3">Product 3</a>
</p>
<p>You selected:
    <b>
     <c:choose>
         <c:when test="${not empty param.product}">${param.product}</c:when>
         <c:otherwise>none yet</c:otherwise>
     </c:choose>

When a user clicks a link, the selected product is appended to the request URL.

http://localhost:8080/magnoliaAuthor/ftl-sample-site/ftl-products/product3

The products virtual URI mapping captures the product from the URL and passes it back to the page as context parameter. It is now available to the script through the ctx templating support object in FreeMarker.

http://localhost:8080/magnoliaAuthor/ftl-sample-site/ftl-products.html?product=product3

The user is forwarded back to the originating page. The forward action prefix ensures the true target URL is not visible to the user. The script displays the context parameter ("You selected: product3") on the page.

Area templates

Pages consist of areas which can consist of further areas or components. Areas structure the page and control what components are available in the area. The area toolbar shows the name of the area. Areas also have an end marker, a narrower green bar that displays at the bottom of the area. For more information see Areas.

Area definitions

Area definitions are configured in the page template definition. In the main page template the areas definitions are in Configuration modules/samples/templates/pages/ftl/main/areas and jsp/main/areas.

An area definition:

  1. Enables and disables the area in the enabled node.
  2. Sets the template renderer in the renderType node.
  3. Defines the template script to use in the templateScript node.
  4. Determines how many components may be added in an area in the typenode. There are three options:
    • single: Area can only contain one component at a time but multiple components can be made available as options. Example: stage area.
    • list: Area can contain multiple components that render in a list. Examples:main, extras and footer areas.
    • noComponent: Area cannot contain any editable components. Used for system-generated automatic content such as breadcrumbs or static content that changes rarely and remains the same across the site such as branding. Example: navigation area.

Available components

Components are made available in the availableComponents node that defines which componets may be added in the area. availableComponents is map of components built by reading the configuration into a Java Bean using the Content2Bean mechanism.

To make a component available in an area, add a content node into the map and reference the component definition. The id property identifies the component definition. The first part before the colon (:) is the name of the module folder where the component definition resides. The second part is the relative path.

Autogeneration

An autoGeneration node in an area definition allows you to create content automatically. An autogenerated component is configured in the extras area of the main template. This configuration in discussed later in Link components. To view the component open the ftl-sample-site or jsp-sample-site page. It is the second component in extras area titled An autogenerated LinkList.

Inheritance

Areas support inheritance which is configured in the inheritance node. The footer area is an example of inheritance. The components in the area cascade down to child pages automatically. Inheritable component are only editable on the source page. For more information see Inheritable components.

In the inheritance node:

  1. The enabled property enables and disables inheritance for the area.
  2. There are three alternatives for the componentsproperty:
    1. none: No components are inheritable. This has the same effect as disabling inheritance by setting the enabled property to false.
    2. all: All components added in the area cascade down to child pages automatically.
    3. filtered: Components in the area cascade only if a Show in subpage checkbox is configured and selected in the component dialog.

Area scripts

The page areas are rendered by four area scripts:

  1. single renders stage area.
  2. list renders main and extras areas
  3. footer renders footer area.
  4. navigation renders the navigation area.

The areas are rendered with containing div elements in the generated HTML so that you can control their layout on the page with CSS. A sample CSS file is included in the module and you can view it in the Git respository.

single script

The single script renders a single component and is suitable for most areas where the type property is set to single in the area definition. The cms.component content tag renders the component content. Compare the code to that of the list script below.

FreeMarker

[#if component?exists]
    [@cms.component content=component /]
[/#if]

JSP

<c:if test="${not empty component}">
   <cms:component content="${component}"/>
</c:if>

list script

The list script can be used for most areas where the type property is set to list in the area definition. The template loops through the components in the area, rendering the them one by one.

In FreeMarker the #List directive lists the content map of components in the availabeComponents node.

<div id="${def.parameters.divId!}">
  [#list components as component ]
      [@cms.component content=component /]
  [/#list]
</div><!-- end  ${def.parameters.divId!} -->

In JSP the tag libraries are referenced specifically and forEach items lists the content map of components in the availabeComponents node.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cms" uri="http://magnolia-cms.com/taglib/templating-components/cms"%>
<div id="${def.parameters.divId}">
  <c:forEach items="${components}" var="component">
    <cms:component content="${component}" />
  </c:forEach>
</div>

footer script

The type property of the footer area is list but the area uses its own script that wraps the content in <div id="footer"> and nests the components in div id="footer-element">.

FreeMarker

<div id="footer">
  [#list components as component ]
      <div id="footer-element">
          [@cms.component content=component /]
      </div><!-- end ${def.parameters.divID!} -->
  [/#list]
</div><!-- end footer -->

JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cms" uri="http://magnolia-cms.com/taglib/templating-components/cms"%>
<div id="footer">
  <c:forEach items="${components}" var="component">
      <div id="footer-element">
            <cms:component content="${component}" />
        </div>
  </c:forEach>
</div>

navigation script

The type property of the navigation area is noComponent and the content is rendered entirely by the navigation script. The include directive includes two further scipts, searchForm that renders the search box and macros/navigation that renders the horizontal navigation. The cmsfn.root method assigns the mgnl:page nodes as children. For more cmsfn methods see TemplatingFunctions .

FreeMarker

[#include "/samples/includes/searchForm.ftl" ]
<div id="navigation">
    [#include "/samples/macros/navigation.ftl"]
    [#assign rootPage = cmsfn.root(content, "mgnl:page")!]
    <ul>[@renderNavigation rootPage /]</ul>
</div><!-- end "navigation" -->

JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cmsfn" uri="http://magnolia-cms.com/taglib/templating-components/cmsfn"%>
<%@include file="/templates/samples/includes/searchForm.jsp" %>
<div id="navigation">
    <c:set var="pageNode" scope="request" value="${cmsfn:root(content, 'mgnl:page')}" />
    <c:set var="maxDepth" scope="request" value="2" />
    <ul><jsp:include page="/templates/samples/macros/navigation.jsp" /></ul>
</div><!-- end "navigation" -->

The navigation bar is rendered by the macros/navigation script. The script uses three cmsfn methods cmsfn.page, cmsfn.link and cmsfn.children.

FreeMarker

[#macro renderNavigation pageNode maxDepth=2 ]
    [#assign currentPage = cmsfn.page(content)]
    [#assign isSelected = (pageNode.@path == currentPage.@path)!false]
    [#if isSelected ]
        <li class="selected"><span>${pageNode.title!pageNode.@name}</span></li>
    [#else]
        <li><a href="${cmsfn.link(pageNode)}"><span>${pageNode.title!pageNode.@name}</span></a></li>
    [/#if]
    [#if pageNode.@depth <  maxDepth]
        [#list cmsfn.children(pageNode, "mgnl:page") as childPage]
            [@renderNavigation childPage /]
        [/#list]
    [/#if]  
[/#macro]

JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cmsfn" uri="http://magnolia-cms.com/taglib/templating-components/cmsfn"%>
<!--  Set Display Name -->
<c:choose>
   <c:when test="${not empty pageNode.title}">
      <c:set var="displayName" value="${pageNode.title}"/>
   </c:when>
      <c:otherwise>
	 <c:set var="displayName" value="${pageNode['@name']}"/>
      </c:otherwise>
</c:choose>
<!-- Get the currentPage -->
<c:set var="currentPage" value="${cmsfn:page(content)}"/>
<!-- Check if the current page is selected -->
<c:set var="selected" value="${pageNode['@path'] == currentPage['@path']}"/>
<c:choose>
   <c:when test="${selected == true}"><li class="selected"><span>${displayName}</span></li></c:when>
      <c:otherwise><li><a href="${cmsfn:link(pageNode)}"><span>${displayName}</span></a></li></c:otherwise>
</c:choose>
<!-- Check maxDepth -->
<c:if test="${pageNode['@depth'] < maxDepth}">
   <c:forEach var="pageNodeSubElement" begin="0" items="${cmsfn:children(pageNode, 'mgnl:page')}">
     <c:set var="pageNode" scope="request" value="${pageNodeSubElement}" />
     <jsp:include page="/templates/samples/macros/navigation.jsp" />
   </c:forEach>
</c:if>

Component templates

Component is the smallest block of content that end users can edit, delete and move as a unit. The Templating Samples module provides seven sample components:

  • howTo renders a title, text, image and date.
  • text renders a title and text.
  • linkList renders a link list.
  • searchResult renders search results.
  • externalLink renders an external link.
  • internalLink renders an internal link.
  • fieldsShowRoom demonstrates various input controls.

The component definitions are in Configuration /modules/samples/templates/components/ftl and /jsp.

As in the case of page and area definitions, a component definition makes the component available to the system and references the script that renders the component. Among others, the definition also typically references the dialog used to edit the component and a model class for additional functionality, but these properties are not strictly necessary.

howTo component

Here is the howTo component on the ftl-sample-site/ftl-howTo page. It is edited with the howTo dialog.

howTo component definition

Here's the component definition for ftl/HowTo:

  • Three properties reference message bundles keys that look up the values used by the component. A bundle is a collection of properties files inside a module JAR. You can view the properties files in the Git repository. Bundles are an efficient way of maintaining data but you can choose not to use them, and safely replace the keys with text.
    • description displays below the title in the selector dialog when the component is added on a page.
    • i18nBasename finds the translations for the description and title properties. For more information see Language.
    • title displays in the selector dialog and in the component toolbar.
  • The modelClass property references the SampleComponentModel . This model class does not add functionality to the this component directly, but can be extended to do so. It's relevance here is the search box that renders in the component that in turn relates to the searchResult component that is discussed later.

Here's the selector dialog in main area on the main template. Match the text in the dialog to that in the messages_en.properties file.

The  JCR Browser allows you to see the content as it is stored in the website repository. You can access the browser at Tools > JCR Browser (Website). This is how the content of the howTo component is stored. Note that the search box and 'HowTo' component link that render on the page are not stored here. This content is rendered entirely by the howTo script.

howTo component script

The howTo script renders the howTo component. Below are examples from the script that show how to create common page content in a component script.

Plain text

Plain text content entered in a dialog is rendered using the content.<field name> notation. The component title text is stored in the title property of the content node, as defined in the howTo dialog definition.

In FreeMarker a tag to check if a content node is empty is not necessary. The ! (exclamation mark) operator provides a default value.

<h3>${content.title!content.@name}</h4. 

In JSP not empty evaluates the body only if a container exists or the corresponding item exists and is not empty.

<h3><c:choose>
    <c:when test="${not empty content.title}">${content.title}</c:when>
    <c:otherwise>${content['@name']}</c:otherwise>
</c:choose></h4. 

FCKEditor text

The text property of the content node contains HTML markup as editorial content is added using the FCKEditor (controlType=fckEdit). The cmsfn TemplatingFunctions expose useful methods. Here the decode method is used to escape the HTML.

FreeMarker

[#if content.text?has_content]<p>${cmsfn.decode(content).text}</p>[/#if]

JSP

<c:if test="${not empty content.text}"><p>${cmsfn:decode(content).text}</p></c:if>

Image

The image is rendered using the cmsfn.link method. The script retrieves the image from the repository at /ftl-sample-site/ftl-howTo/main/0/image/<image name.ext>.

FreeMarker

[#if content.image?has_content]Image: <img src="${cmsfn.link(content.image)}" />
...
[/#if]

JSP

<c:choose>
   <c:when test="${not empty content.image}">Image: <img src="${cmsfn:link(content.image)}" />
   </c:when>
...
</c:choose>

Date

The date is stored in the repository in the mm/dd/yy format. The following code renders and reformats the date as EEEE, d. MMMM yyyy.

FreeMarker

[#if content.date?has_content]The date you specified: ${content.date?string("EEEE, d. MMMM yyyy")}
...
[/#if]

JSP

<c:choose>
  <c:when test="${not empty content.date}">
     <fmt:formatDate value="${content.date.time}" var="parsedDate" pattern="EEEE, d. MMMM yyyy" />
        The date you specified: <c:out value="${parsedDate}" />
  </c:when>
...
</c:choose>

Search box

The include directive includes the includes/searchForm script that renders the search box. This script is used multiple times in the samples. It is also included in the navigation script and searchResult script.

FreeMarker

[#include "/samples/includes/searchForm.ftl" ]

JSP

<%@include file="/templates/samples/includes/searchForm.jsp" %>

Link

The 'HowTo' component link opens the component script file. Click the link on the page in preview mode to view the script in the browser. The DisplaySamplesSourcesServlet is executed when the requested path contains the pattern /.sources/*. For more see Servlets below. The script provides an example of creating links by appending a static path to the context path.

In FreeMarker you can get the current context path from the ctx templating support object.

<li><a href="${ctx.contextPath}/.sources/components/howTo.ftl">'HowTo' component</a>/li>

JSP

<li><a href="${pageContext.request.contextPath}/.sources/components/howTo.jsp">'HowTo' component</a></li>

Link components

The linkList component is an example of a component that contains nested components. It is also used to demonstrate the configuration of an autogenerated component. Note how efficiently elements can be used multiple times.

A number of link components are available on pages based on main template:

  • linkList components can be added in main, extras and footer areas.
  • An autogenerated linkList component is rendered in extras area.
  • Individual internalLink and externalLink components can be made available in any area, if preferred.

Link component definitions

Here's how the various definitions interrelate.

The internalLink and externalLink components are used in the samples as nested components in the linkList component. The component definitions are in Configuration modules/samples/templates/components/ftl and jsp. Both components are rendered by the link script. The externalLink component does not require or use a model class and the internalLink component uses the InternalLinkModel class that resolves internal links by identifier or path.

The linkList component defintion is in Configuration modules/samples/templates/components/ftl/linkList and jsp/linkList. Nested components are configured in the areas/links/availableComponents node. Note that this node has an almost identical structure to the corresponding areas/<area name>/availableComponents node in the page template definitions. Here <area name> is substituted with the links node. This structure identifies that the nested components reside within a sub area (node type=mgnl:area) and are rendered by the script using the cms.area name="links" tag. See Link component scripts below.

An autogenerated linkList component is configured in the main page template in Configuration modules/samples/pages/ftl/main/areas/extras/autoGeneration and /jsp/main/areas/extras/autoGeneration. Here the links that are rendered on the page are defined in the definition:

  1. The CopyGenerator class defined in the autoGeneration/generatorClass node allows for the nodes and properties within the configuration.
  2. The nodeTypes are defined as follows:
    • autoGenerated node is mgnl:component.
    • autoGenerated/links node is mgnl:area.
    • auotGenerated/links/internal and external nodes are mgnl:component.
  3. The autoGeneratednode:
    • Defines the title of the main component in the title property.
    • References the linkList component in the templateID property that in turn references the linkList script that renders the main component.
  4. The autotGenerated/links/internal and externalnodes:
    • Define the link target and title in the target and title properties of the nested components.
    • Reference the nested component definitions in the templateId property. These component definitions, samples:components/ftl/internalLink and samples:components/ftl/externalLink in turn reference the link script that renders the links.

Here is the autogenerated component on the ftl-sample-site/ftl-howTo page. The component is created atuomatically on all pages based on the main page template.

Link component scripts

Two relatively simple scripts combine to render the numerous link components.

link script

The internalLink and externalLink components are rendered by the link script.

The InternalLinkModel makes the internal link properties available to the script and the model.targetLink notation is used. The title of the target page renders as the link title unless another title is specified.

External links are rendered using the standard content.<field name> notation.

FreeMarker

[#assign target = model.target!]
[#if target?has_content]
<li><a href="${model.targetLink!}">${content.title!target.title!target.@name}</a></li>
[#else]
<li><a href="${content.target!}">${content.title!content.target!}</a></li>
[/#if]

JSP

...
<c:catch  var="exception"><c:set var="target" scope="request" value="${model.target}" /></c:catch>
<c:if test="${empty exception}"><li><a href="${model.targetLink}">
   <c:choose>
      <c:when test="${not empty content.title}">${content.title}</c:when>
      <c:when test="${empty content.title and not empty target.title}">${target.title}
      </c:when>
         <c:otherwise>${target['@name']}</c:otherwise>
   </c:choose></a></li>
</c:if>
<c:if test="${not empty exception}"><li><a href="${content.target}">
   <c:choose>
        <c:when test="${not empty content.title}">${content.title}</c:when>
            <c:otherwise>${content.target}</c:otherwise>
   </c:choose></a></li>
</c:if>

linkList script

The linkList script renders the linkList component. The links of the nested components are in a nested <div class> and are rendered using the cms.area name tag because the component definition is structured to identify their node as an area.

FreeMarker

[#if content.title?has_content]
<h3>${content.title}</h4. 
[/#if]
<div class="linkList">
  <ul>[@cms.area name="links" /]</ul>
</div>

JSP

...
<c:if test="${not empty content.title}"><h3>${content.title}</h3></c:if>
<c:if test="${not empty content.text}"><h4>${content.text}</h4></c:if>
<div class="linkList">
    <ul><cms:area name="links" /></ul>
</div>

searchResult component

The searchResult component renders the results of a search term entered in the search box. A page containing this type of component would normally be excluded from the navigation as it only renders meaningful content when a search is executed. For demonstration purposes the component is included on the ftl-sample-site/ftl-searchResult and jsp-sample-site/jsp-searchResult pages.

Here's the FreeMarker component after requesting the results for the term "ftl".

searchResult component definition

The component definitions are in Configuration modules/samples/templates/components/ftl/searchResult and jsp/searchResult. The component uses the searchResult script and SampleComponentModel model class.

SampleComponentModel class

SampleComponentModel model class contains the Jave logic that renders the search results. The class gets and sets the query string and lists the search results using the following SQL query.

String sql = "SELECT * from nt:base WHERE jcr:path like '"+rootPagePath+"/%' AND contains(*, '"+query+"') AND (jcr:primaryType = 'mgnl:page' OR jcr:primaryType = 'mgnl:area' OR jcr:primaryType = 'mgnl:component') order by jcr:path";

searchResult script

The searchResult script renders the results from the attributes made available by the model. Note the use of the cmsfn.page method made available by TemplatingFunctions and the use of the ctx templating support object. Here's the part of the script that renders the results.

FreeMarker

...
[#if model.searchResult?has_content]
    <div id="search-results" >
        <h3>Query Results for: "${model.query!"No query set yet"}"</h4. 
        <ul>
            [#list model.searchResult as resultItem]
                [#assign foundOnPage = cmsfn.page(resultItem)]
                <li><a href="${ctx.contextPath}${foundOnPage.@path}">${foundOnPage.title!foundOnPage.@name}</a><span>(found in Node: ${resultItem.@path})</span></li>
            [/#list]
        </ul>
    </div><!-- end search-results -->
[/#if]
...

JSP

...
<c:if test="${not empty model.searchResult}">
   <div id="search-results" ><h3>Query Results for:
      <c:choose><c:when test="${not empty model.query}">${model.query}</c:when>
        <c:otherwise>No query set yet</c:otherwise>
      </c:choose>
        </h3><ul><c:forEach items="${model.searchResult}" var="resultItem"><c:set var="foundOnPage" value="${cmsfn:page(resultItem)}"/><li>
          <a href="${pageContext.request.contextPath}${foundOnPage['@path']}">
            <c:choose>
              <c:when test="${not empty foundOnPage.title}">${foundOnPage.title}</c:when>
              <c:otherwise>${foundOnPage['@name']}</c:otherwise>
            </c:choose>
          </a><span>(found in Node: ${resultItem['@path']})</span></li>
      </c:forEach></ul>
  </div><!-- end search-results -->
...

Servlets

DisplaySamplesSourcesServlet is an example of a custom servlet. Its purpose is to display the source file of a template or component script.

The servlet is registered in the servlets filter chain at Samples > Servlets /server/filters/servlets/DisplaySamplesSourcesServlets. It is executed when the requested path contains the pattern /.sources/*.

The /.sources/* pattern is present in the *Display Component's Sources * links that render in the howTo and searchResults components. When you click these links the servlet loads the source of the howTo or searchResult scripts.

For more information see Filters.

Bootstrap samples

The module installs a number of sample users, groups and roles to show how the bootstrap mechanism work. Bootstrapping is the process of pre-loading the system with content and configuration. This is useful when you want to load some data as a baseline for testing.

The Templating Samples module JAR has two bootstrap folders:

  • mgnl-bootstrap contains files that are always bootstrapped. In the Templating Samples module dialog, template, virtualURIMapping, config definitions and the base user role are loaded from here.
  • mgnl-bootstrap-samples contains files that are bootstrapped only if magnolia.bootstrap.samples property is set to true. Web pages, users, groups and roles are loaded from here.

You can find the sample users, groups and roles in the Security menu in AdminCentral.

In Configuration modules/samples/config there are a number of sample configurations. These are provided as examples and are not used by the module as such.