1 General description
The CMS uses the handlebars.java implementation of Handlebars.
For a general introduction to the Handlebars templating language, see the Handlebars Guides.
2 Usage
To render a Handlebars template, you only need to add a “Handlebars” part to a tagtype. The part will use its own input as template.
Below is an example of a construct with a single “Handlebars” part, that is not hidden and will render the template {{ cms.page.name }} (which will output the current page’s name).
3 Resolving
The context of a rendered Handlebars part will always contain the base object cms which can be used to resolve some base objects:
- cms.node resolves to the node of the currently rendered object.
- cms.folder resolves to the folder of the currently rendered object (or the rendered folder).
- cms.page resolves to the currently rendered page (if the tag is rendered in a page).
- cms.template resolves to the template of the currently rendered page (of the tag is rendered in a page).
- cms.file resolves to the currently rendered file/image (of the tag is rendered in a file/image).
- cms.object resolves to the object tags of the currently rendered object.
- cms.rendermode resolves to the rendermode information.
To find out all possible attributes that can be resolved from the base object “cms”, you can use something like {{#each cms}}{{ @key }}:{{ this }}
{{/each}}. This obviously does not only work for “cms”, but for every object in the context.
Unlike the Velocity Part Type, the Handlebars Part Type does not support “shortcuts” when resolving. So for example to resolve a specific part in the current tag, it is not allowed to omit the “parts” keyword in handlebars: {{ cms.tag.parts.html }} will resolve to the part “html” in the current tag, whereas {{ cms.tag.html }} will not work.
4 Helpers
Since Handlebars templating language itself is completely Logic-less, the Handlebars Part Type provides some helpers for supporting more complex rendering logic:
4.1 Built-in Helpers
All Built-in helpers are supported.
4.2 Conditional Helpers
All Conditional Helpers provided by handlebars.java are supported.
4.3 String Helpers
All String Helpers provided by handlebars.java are supported.
4.4 Additional Helpers
Name | Description | Example |
---|---|---|
gtx_render | Render another object (e.g. a tag, page, …) | {{{gtx_render cms.page.tags.othertag }}} |
gtx_edit | Like gtx_render, but will render the object in edit mode (if possible) | {{{gtx_edit cms.page.tags.othertag }}} |
gtx_sort | Sort a list of objects by the given attribute (which might be a path to resolve) | {{#each (gtx_sort cms.folder.folders "name"}}{{name}}<br>{{/each}} |
gtx_channel | Render the block in the scope of the given channel | {{#gtx_channel cms.tag.parts.node.target}}<a href="{{ cms.page.url }}">{{ cms.page.name }}</a>{{/gtx_channel}} |
gtx_gis | Include a resized image into the output | <img src="{{gtx_gis cms.tag.parts.image width=100 mode="prop" }}"> |
gtx_form | Include a form | {{gtx_form cms.tag.parts.form type="java" }} |
gtx_i18n | Include a translation in the language of the currently rendered page | {{gtx_i18n de="Deutsch" en="English" default="Other language" }} |
4.4.1 gtx_render
This helper will render the given object (if it is e.g. a tag or a page) or output the String representation of anything else.
General usage is:
{{gtx_render object}}
With the parameters
Name | Description | Default |
---|---|---|
object | Object to be rendered | mandatory |
When using double curly braces, HTML code rendered from the object will be escaped. If HTML code should not be escaped, triple curly braces have to be used, see HTML Escaping for details.
The helper can also be used in combination with other helpers (conditional helpers for example) like shown in the following example:
{{! Iterate over all subfolders of the current folder }} {{#each cms.folder.folders}} {{! Omit folders, that have the checkbox in the object property "navhidden" checked }} {{#neq (gtx_render this.object.navhidden) "1"}} {{! Output the name of the folder }} {{name}}<br> {{/neq}} {{/each}}
Since gtx_render will always output a String, the comparison must also be done with the String (“1”) and not with the Integer (1).
Unlike Velocity, the Handlebars Part Type will only render objects if the gtx_render helper is used. Simply referencing like {{{ cms.page.tags.othertag }}} will not render the other tag, but will output some information about the referenced object.
4.4.2 gtx_edit
This helper is a variant of the gtx_render helper, which will render the object in edit mode, if possible.
General usage is:
{{{gtx_edit object}}}
With the parameters
Name | Description | Default |
---|---|---|
object | Object to be rendered | mandatory |
4.4.3 gtx_sort
This helper can be used to sort objects by attributes (or even attribute paths).
General usage is:
{{gtx_sort list sortBy [sortOrder]}}
With the parameters
Name | Description | Default |
---|---|---|
list | Objects to be sorted | mandatory |
sortBy | Attribute (or Attribute path) by which the objects shall be sorted | mandatory |
sortOder | asc for sorting in ascending order, desc for descending order | asc |
The gtx_sort helper will in most cases be used together with the each
helper:
{{! Iterate over all subfolders of the current folder, sorted by the object property "navsortorder" }} {{#each (gtx_sort cms.folder.folders "object.navsortorder" "asc")}} {{! Omit folders, that have the checkbox in the object property "navhidden" checked }} {{#neq (gtx_render this.object.navhidden) "1"}} {{! Output the name of the folder and the navsortorder }} {{name}} ({{gtx_render object.navsortorder}})<br> {{/neq}} {{/each}}
As can be seen in the example above, the gtx_sort helper will resolve the attribute path for each object, if the resolved values (tags in this case) are something that can be rendered, it will render them, and if all values are numerical, the sorting will be done numerical.
4.4.4 gtx_channel
This is a block helper, which will switch the rendering scope to the given channel for the block.
General usage is:
{{#gtx_channel node}} block {{/gtx_channel}
With the parameters
Name | Description | Default |
---|---|---|
node | Reference to the node/channel. | mandatory |
The reference to the node/channel can be one of
- local ID of a node/channel
- global ID of a node/channel
- A resolved node/channel object
- Tag part of type “Node”
4.4.5 gtx_gis
This helper will either render a Gentics Image Store URL for a resized image, or – when used for an installation of Gentics Portal | php – a widget that will resize that image.
General usage is:
{{gtx_gis image [width=value] [height=value] [mode=value] [type=value] [crop_width=value] [crop_height=value] [crop_x=value] [crop_y=value]}}
With the parameters
Name | Description | Default |
---|---|---|
image | Reference to the image. | mandatory |
width | Width of the resized image | auto |
height | Height of the resized image | auto |
mode | Resizing mode (“prop”, “force”, “smart”, “fpsmart”) | prop |
type | Type of the rendering (“url”, “phpwidget”) | url |
crop_width | Cropping width | mandatory |
crop_height | Cropping height | mandatory |
crop_x | Start X coordinate of the image area (from the top left corner) | 0 |
crop_y | Start Y coordinate of the image area (from the top left corner) | 0 |
The reference to the image can be one of
- local ID of an image
- global ID of an image
- A resolved image object
- Tag part of type “Image”
For details see Gentics CMS GenticsImageStore.
4.4.6 gtx_form
This helper will include a CMS form into the tag.
General usage is:
{{{gtx_form form [type=value] [previewRoot=value] [showResults=value] [templateContext]=value }}}
or (as block helper)
{{#gtx_form [type=value] [previewRoot=value] [showResults=value] [templateContext]=value}} {{{this}}} {{else}} no-form-block {{/gtx_form}}
With the parameters
Name | Description | Default |
---|---|---|
form | Reference to the form | mandatory |
type | Type of used portal. Must be either java or php | java |
previewRoot | HTML Element, which should be rendered as root element for the preview | div |
templateContext | Additional path segments for templates used to render the form. The actual path used is the templatesPath (from plugin configuration) + /templateContext. | (empty) |
showResults | Boolean flag to force rendering results of a poll instead of the form itself. (This has no effect on non-poll forms.) | false |
no-form-block | Block that is rendered when no form was selected. | (empty) |
The reference to the form can be one of
- local ID of a form
- global ID of a form
- A resolved form object
- Tag part of type “Form”
4.4.7 gtx_i18n
This helper can be used to render language specific output (in the language of the current page).
General usage is:
{{gtx_i18n [object] [de=value] [en=value] ... [default=value]}}
With the parameters
Name | Description | Default |
---|---|---|
object | Optional object to resolve the translation (from the language code) | (empty) |
de | Optional german translation | (empty) |
en | Optional english translation | (empty) |
[language code] | Optional translation for the given language code | (empty) |
default | Optional default translation | (empty) |
Translations given as parameters always take precedence over translations resolved from an optionally given object.
The helper will first try to get the translation for the current page language (if rendered for a page and the page has a language).
Then it will fall back to the remaining languages of the current node (if the node has languages assigned).
Finally it will fall back to “default”.
If no translation is found, it will render nothing.
4.5 Custom helpers
For implementation of custom logic, it is possible to create helpers as Javascript files in devtool packages.
Every .js file located in the directory /cms/packages/[package]/handlebars/helpers/ is interpreted as a handlebars helper.
The name of the file (without extension) defines the name of the helper, which will be prefixed with the packagename to avoid naming conflicts. The file must contain a single JavaScript function (the name of that function does not matter).
For example:
function get_name(obj) { return obj.name; }
will be available as helper implementation_package.get_name and can be used like this:
{{implementation_package.get_name cms.page}}
If an additional options
parameter is added at the end of the argument list, Handlebars will automatically fill this parameter with an object giving access to the hash arguments as well as the options.fn()
and options.reverse()
function. Calling options.fn(ctx)
will render the contents of the helper with the given context ctx
, and options.reverse(ctx)
will render the else
block. The name of the options
parameter can be chosen freely, but it must be the last parameter in the list. The following example assumes that the given tag has two text parts short_desc
and long_desc
as well as a checkbox part inline
. The helper is supposed to render the tag with the content-block if inline
is checked and with the else-block otherwise. To include hash arguments, it will also generate the string containing a title
attribute if present:
function render_tag(tag, options) { let ctx = {}; if (options.hash.title) { ctx['title'] = ' title="' + encodeURIComponent(options.hash.title) + '"'; } if (tag.parts.inline.checked) { ctx['message'] = tag.parts.short_desc.text; return options.fn(ctx); } ctx['message'] = tag.parts.long_desc.text; return options.fn(ctx); }
Usage of the helper:
{{#implementation_package.render_tag cms.tag title='Tag title'}} <span{{title}}>{{message}}</span> {{else}} <p{{title}}>{{message}}</p> {{/implementation_package.render_tag}}
4.5.1 Default package helpers
Currently the only tagtype in the default package that uses Handlebars is the Aloha Page Link Tag which uses the gtx_alohalink
helper also contained in the default package. Since helpers must always be prefixed with their respective package names, a custom implementation of the Aloha Page Link Tag requires adding the tag to a custom package, then adding a custom helper for use in the Handlebars part and calling that helper with the package prefix (see the Aloha Page Link Tag guide).
Helpers defined in devtool packages will only be available, if the devtool package is assigned to the Node for which the object is currently rendered!
Helpers will not be synchonized into the CMS, so changes in a helper file will be effective immediately.
5 Partials
For reusing templates, it is possible to define Partials as files in devtool packages.
Every .hbs file located in the directory /cms/packages/[package]/handlebars/partials/ is interpreted as a handlebars partial.
The name of the file (without extension) defines the name of the partial, which will be prefixed with the packagename to avoid naming conflicts.
For example:
{{ name }}
will be available as partial implementation_package.render_name and can be used like this:
{{> implementation_package.render_name cms.page }}
Partials will not be synchonized into the CMS, so changes in a partial file will be effective immediately.
6 Differences to Velocity
This section will cover some differences between the Velocity PartType and the Handlebars PartType (apart from the obvious difference in templating language syntax), which hopefully will help with migration of implementations.
Velocity | Handlebars | |
---|---|---|
Construct setup | The Velocity PartType needs another PartType with keyword template which contains the template to render. | The Handlebars PartType will use its own content as template. |
Rendering of objects | Direct references to objects that can be rendered will render them (e.g. $cms.page.tags.html will render the tag html). | Direct references will not render the object, but will output some textual description. For rendering the gtx_render (or gtx_edit) helper must be used. |
Resolving shortcuts | Velocity supports various shortcuts, so e.g. $cms.tag.partname will resolve the part partname in the tag as well as $cms.tag.parts.partname does. | Shortcuts are not supported in the Handlebars PartType, so in order to resolve a specific part of a tag, the parts keyword must be used: {{ cms.tag.parts.partname }} |
Reusable templates | The Velocity PartType supports both locally defined and globally configured macros | The Handlebars PartType supports partials, which must be defined in devtool packages. |
Programmatic logic | Velocity supports programmatic logic like defining variables, calling various methods of objects and even instantiation of new objects. | Handlebars is logic-less but supports programmatic logic via helpers (built-in or custom) which guarantees a clean separation between business logic and presentation. |
HTML Escaping | Velocity does not escape HTML by default, so for instance the EscapeTool must be used for that purpose. | Handlebars does HTML Escaping when two curly braces are used and omits HTML Escaping upon three curly braces. |