Views
FreeMarker Template Cookbook
From alfrescowiki
All examples below are complete templates and use the FreeMarker template language and using the default Alfresco Template Model. Please add your own examples to make this cookbook more versatile.
Example Presentation Templates
Overview
Use this area to share presentation templates. Sharing examples is a great way for others to learn how to create presentation templates, and avoids reinventing the wheel.
Creating presentation templates
The Template Guide provides a good introduction to creating presentation templates.
Information to provide for each template
Provide this information for each template:
- Title: A short succinct title for the presentation template.
- Description: A brief description of what the template does or can be used for.
- Screen shot: A screen shot of the template - to show what the template looks like.
- Template: The code for the template.
- Requirements: Anything that needs to be in place before the template can be used.
- Source: Where the idea for the template came from, if applicable.
Use this naming standard for each template:
- Example_Template_<Name>, for example Example_Template_Notice
Index of Other Pages With Template Samples
Example Recursive Template
Example of how to recurse down a set of spaces and print out some information.
Example Template Notice
For posting important notices on the Company Home page, or in any other spaces.
Thumbnails Template
For displaying the images within a space in a 3 column list of clickable thumbnails.
List of Inbound Rules
For displaying all inbound rules, given the current space, traversing all sub spaces.
Audit Script
For displaying audit information for a document.
- Add a link to your presentation template here .....
Don't have time to prepare all of this information?
If you have a great template, but don't have time to tidy it up, post it to this forum topic. Someone may tidy it up and update the wiki for you!
Examples
Simple Examples
Display the Company Home Space name:
<b>Company Home Space:</b> ${companyhome.properties.name}
The number of nodes below the users Home Space:
<b>My Home Space children count:</b> ${userhome.children?size}
Whether a node called document is currently locked:
<b>Locked:</b> <#if document.isLocked>Yes<#else>No</#if>
Note: To access property "my:myprop" defined within an aspect, only the second notation below will work:
<b>wrong:</b> ${document.properties.myprop} <br>
<b>ok:</b> ${document.properties["my:myprop"]}
Document Properties Example
Iterate over all properties for a node called document, and render the values as appropriate for the data-types returned:
<table>
<#-- Get a list of all the property names for the document -->
<#assign props = document.properties?keys>
<#list props as t>
<#-- If the property exists -->
<#if document.properties[t]?exists>
<#-- If it is a date, format it accordingly-->
<#if document.properties[t]?is_date>
<tr><td>${t} = ${document.properties[t]?date}</td></tr>
<#-- If it is a boolean, format it accordingly-->
<#elseif document.properties[t]?is_boolean>
<tr><td>${t} = ${document.properties[t]?string("yes", "no")}</td></tr>
<#-- Otherwise treat it as a string -->
<#else>
<tr><td>${t} = ${document.properties[t]}</td></tr>
</#if>
</#if>
</#list>
</table>
Hard Coded NodeRef
Find a node from a hardcoded NodeRef value:
Found: ${companyhome.nodeByReference["workspace://SpacesStore/e661dccb-ecc0-11da-9974-63f65406985a"].id}
Search Examples
Using XPath
List folders in 'Company Home/Data Dictionary/Space Templates/Software Engineering Project' folder using an XPath query:
<table>
<#list companyhome.childrenByXPath["*[@cm:name='Data Dictionary']/*[@cm:name='Space Templates']/*[@cm:name='Software Engineering Project']/*"] as child>
<#if child.isContainer>
<tr><td><img src="/alfresco${child.icon32}"> ${child.properties.name}</td></tr>
</#if>
</#list>
</table>
Using Lucene Full-Text Search
Execute a Lucene full-text search and list the resulting documents:
<table>
<#list companyhome.childrenByLuceneSearch["TEXT:alfresco* AND TEXT:tutorial*"] as child>
<tr><td><a href="/alfresco${child.url}" target="new">${child.properties.name}</a></td></tr>
</#list>
</table>
Using Lucene By Node ID
Find a node by its ID Node reference using Lucene, note the escaping needed to satisfy both FreeMarker and Lucene language:
<#list companyhome.childrenByLuceneSearch["ID:workspace\\:\\/\\/SpacesStore\\/e661dccb-ecc0-11da-9974-63f65406985a"] as node>
Found: ${node.id}<br>
</#list>
Using Lucene with a More Complex Search
Find nodes of specific file types in a specific subspace that are recently modified or created using Lucene. This can be saved in Data Dictionary/Presentation Templates and then selected for use on the subspace. Note the escaping needed to satisfy both FreeMarker and Lucene language:
<h3>Documents from a test space, Test_Space, of types PDF or jpeg images that were created in a 4 day range</h3>
<table cellpadding=2>
<tr>
<td></td>
<td><b>Name</b></td>
<td><b>Created Date</b></td>
<td><b>Modified Date</b></td>
</tr>
<#-- a couple of things to note: you must '\' escape the '\' escapes and '"' quotes so they get handed through
the templating engine to the Lucene engine. Also, Company Home is an application object, not a content object.
The '//*' on the end of the PATH parameter is the Lucene syntax to search a node and, recursively, all sub-nodes.
http://wiki.alfresco.com/wiki/Search#Path_Queries Note in the date range, that the times, in the stock
Alfresco configuration, are ignored. The time component must exist for the syntax of the query, but it is not used.
{See http://forums.alfresco.com/en/viewtopic.php?f=4&t=9122 to configure the datetimeanalyzer}
-->
<#list space.childrenByLuceneSearch["
+(@cm\\:modified:[2008-11-10T00:00:00 TO 2008-11-14T23:59:59]
OR
@cm\\:created:[2008-11-10T00:00:00 TO 2008-11-14T23:59:59])
+(@\\{http\\://www.alfresco.org/model/content/1.0\\}content.mimetype:image/jpeg
OR
@\\{http\\://www.alfresco.org/model/content/1.0\\}content.mimetype:application/pdf)
+PATH:\"/app:company_home/cm:Test_Space//*\"
"] as child>
<tr>
<td><a href="/alfresco${child.url}" target="new"><img src="/alfresco${child.icon16}" border=0></a></td>
<td><a href="/alfresco${child.url}" target="new">${child.properties.name}</a></td>
<td>${child.properties["cm:created"]?datetime}</td>
<td>${child.properties["cm:modified"]?datetime}</td>
</tr>
</#list>
</table>
Documents in User's Home Space Example
Renders a tabular list of all the documents in the users Home Space, and display the content of any plain text documents directly inline, and any JPG documents are shown as inline thumbnails:
<table>
<#list userhome.children as child>
<#if child.isDocument>
<tr><td>${child.properties.name}</td></tr>
<#if child.mimetype = "text/plain">
<tr><td style='padding-left:16px'>${child.content}</td></tr>
<#elseif child.mimetype = "image/jpeg">
<tr><td style='padding-left:16px'><img width=100 height=65 src="/alfresco${child.url}"><td></tr>
</#if>
</#if>
</#list>
</table>
Display SubSpaces Example
Display all the Spaces under the Company Home Space in a table, with the appropriate space icon next to the name, and the number of child spaces is shown in brackets next to the folder name:
<table>
<#list companyhome.children as child>
<#if child.isContainer>
<tr>
<td><img src="/alfresco${child.icon32}"></td>
<td><b>${child.properties.name}</b> (${child.children?size})</td>
</tr>
</#if>
</#list>
</table>
Display Document Information Example
Display information on a TemplateNode in the model called 'document':
<b>Name:</b> ${document.name}<br>
<b>Ref:</b> ${document.nodeRef}<br>
<b>Type:</b> ${document.type}<br>
<b>Content URL:</b> <a href="/alfresco${document.url}">/alfresco${document.url}</a><br>
<b>Locked:</b> <#if document.isLocked>Yes<#else>No</#if><br>
<b>Aspects:</b>
<table>
<#list document.aspects as aspect>
<tr><td>${aspect}</td></tr>
</#list>
</table>
Walk Association Example
If the document has the 'translatable' aspect applied, walk the 'translations' association and view the content of the node at the end of the association:
<b>Translatable:</b>
<#if document.assocs["cm:translations"]?exists>
Yes
<br>
<table>
<#list document.assocs["cm:translations"] as t>
<tr><td>${t.content}</td></tr>
</#list>
</table>
<#else>
No
</#if>
List all the Template Documents in 'Company Home/Data Dictionary/Content Templates' folder
<table>
<#list companyhome.childByNamePath["Data Dictionary/Content Templates"].children as child>
<#if child.isDocument>
<tr><td><a href="/alfresco${child.url}" target="new">${child.properties.name}</a></td></tr>
</#if>
</#list>
</table>
Classification Example
Display the available classification types and top level category nodes:
<#list classification.allClassificationAspects as a>
${a}<br>
</#list>
<p>
<#list classification.getAllCategoryNodes("cm:generalclassifiable") as n>
${n.name}<br>
</#list>
Example - Show Version History
Show version history for the current document, with links to content for the previous versions:
<#if document?exists>
<h3>Document Version History for: ${document.name}</h3>
<table cellspacing=4>
<tr align=left><th>Version</th><th>Name</th><th>Description</th><th>Created Date</th><th>Creator</th></tr>
<#list document.versionHistory as record>
<tr>
<td><a href="/alfresco${record.url}" target="new">${record.versionLabel}</a></td>
<td><a href="/alfresco${record.url}" target="new">${record.name}</a></td>
<td><#if record.description?exists>${record.description}</#if></td>
<td>${record.createdDate?datetime}</td>
<td>${record.creator}</td>
</tr>
</#list>
</table>
<#else>
No document found!
</#if>
WCM Web Forms
List the available WCM Web Form objects in all web projects the current user is assigned to:
<table cellspacing=2 cellpadding=2 border=0>
<#assign search="TYPE:\"{http://www.alfresco.org/model/wcmappmodel/1.0}webfolder\"">
<#list companyhome.childrenByLuceneSearch[search] as wp>
<#list wp.childAssocs["wca:webuser"] as user>
<#if user.properties["wca:username"] = person.properties.userName>
<tr><td><a href="${url.context}${wp.url}">${wp.name}</a></td></tr>
<tr>
<td style='padding-left:16px'>
<table cellspacing=2 cellpadding=2 border=0>
<#if wp.childAssocs["wca:webform"]?exists>
<#list wp.childAssocs["wca:webform"] as form>
<tr><td>${form.properties["wca:formname"]}</td><tr>
</#list>
</#if>
</table>
</td>
</tr>
</#if>
</#list>
</#list>
</table>
Workflow Tasks Example
Workflow Tasks todo for the current user:
My Tasks Todo:
<table cellspacing=0 cellpadding=2>
<tr>
<th>ID</th>
<th>Type</th>
<th>Name</th>
<th>Description</th>
<th>Created Date</th>
<th>Start Date</th>
<th>Due Date</th>
<th>Priority</th>
<th>% Complete</th>
<th>Status</th>
<th>Completed</th>
<tr>
<#list workflow.assignedTasks as t>
<tr>
<td>${t.id}</td>
<td>${t.type}</td>
<td>${t.name}</td>
<td>${t.description}</td>
<td>${t.properties["cm:created"]?datetime}</td>
<td><#if t.properties["bpm:startDate"]?exists>${t.properties["bpm:startDate"]?datetime}<#else><i>None</i></#if></td>
<td><#if t.properties["bpm:dueDate"]?exists>${t.properties["bpm:dueDate"]?datetime}<#else><i>None</i></#if></td>
<td>${t.properties["bpm:priority"]}</td>
<td>${t.properties["bpm:percentComplete"]}</td>
<td>${t.properties["bpm:status"]}</td>
<td>${t.isCompleted?string("Yes", "No")}</td>
</tr>
</#list>
</table>
XML Document Example
Process the XML document content of a node called 'document', assuming the node content contains the following XML:
<?xml version="1.0" standalone="yes"?>
<book title="Book Title">
<chapter>
<title>Chapter 1</title>
<para>p1.1</para>
<para>p1.2</para>
<para>p1.3</para>
</chapter>
<chapter>
<title>Chapter 2</title>
<para>p2.1</para>
<para>p2.2</para>
</chapter>
</book>
<#if document.mimetype = "text/xml">
<#assign dom=document.xmlNodeModel>
<h1>${dom.book.@title}</h1>
<#list dom.book.chapter as c>
<h2>${c.title}</2>
</#list>
</#if>
Externalized Browse View Example
Different externalized browse view (see screenshot below), this example shows the contents of the repository in a simple HTML view without all the usual Alfresco UI adornments. This could be used as an example on how to build a custom website on top of the Alfresco repository. This is also a neat example of an "interactive" template. Note that we now recommend using the new Web Scripts REST based API to create interaction templates.
Don't forget to replace the two [TEMPLATE] strings with the reference to this template (/workspace/SpacesStore/<templateID>) the default template will be used otherwise and this will generate an error when no default template is set for this node.
View your template by pointing your browser to: http://localhost:8080/alfresco/template/workspace/SpacesStore/<spaceID>/workspace/SpacesStore/<templateID>
<html>
<head>
<title>View ${space.name} space</title>
</head>
<body>
<img src="/alfresco${space.icon32}" alt="Space">
<ul>
<li>Name: <strong>${space.name}</strong></li>
<li>Type: ${space.type}</li>
<li>Path: ${space.displayPath}</li>
<li>Parent: <a href="/alfresco/template/workspace/SpacesStore/${space.parent.id}[TEMPLATE]" title="Up to ${space.parent.name}">${space.parent.name}</a></p></li>
</ul>
<h1>Spaces</h1>
<ul>
<#list space.children as child>
<#if child.isContainer>
<li><img src="/alfresco${child.icon16}" alt="Space"> <a href="/alfresco/template/workspace/SpacesStore/${child.id}[TEMPLATE]" title="Browse to ${child.properties.name}">${child.properties.name}</a></li>
</#if>
</#list>
</ul>
<h1>Documents</h1>
<ul>
<#list space.children as child>
<#if child.isDocument>
<li>
<a href="/alfresco${child.url}" title="Download this file">${child.properties.name}</a>
</li>
</#if>
</#list>
</ul>
</body>
</html>
Example - Show Version History for a Folder
Show version history for all documents in the current folder, with links to content for the previous versions:
<table>
<tbody>
<tr>
<td><h1>Version History - ${space.name}<h1></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th class="recordSetHeader"></th>
<th class="recordSetHeader">Creator</th>
<th class="recordSetHeader">Document</th>
<th class="recordSetHeader">Version</th>
<th class="recordSetHeader">Created Date</th>
</tr>
<#assign i = 0/>
<#list space.childrenByXPath[".//*[subtypeOf('cm:content')]"] as child>
<#if child.isDocument>
<#list child.versionHistory as record>
<tr class="${(i % 2 = 0)?string("recordSetRow","recordSetRowAlt")}">
<td style="padding: 2px; text-align: center;"><b>${i+1}</b></td>
<td style="padding: 2px; text-align: center;">${record.creator}</td>
<td style="padding: 2px; text-align: left;"><a href="/alfresco${record.url}" target="new">${record.name}</a></td>
<td style="padding: 2px; text-align: center;">${record.versionLabel}</td>
<td style="padding: 2px; text-align: center;">${record.createdDate?datetime}</td>
</tr>
<#assign i = i + 1 />
</#list>
</#if>
</#list>
</table>



