Handlebars Training Manual
T205: Terminalfour Handlebars
Handlebars is a versatile templating engine designed to simplify the process of creating dynamic content. For those who are unfamiliar with Handlebars, think of it as a tool that bridges the gap between static HTML and dynamic data.
Overview
Handlebars allows you to create Content Layouts and Page Layouts with placeholders and simple logic that will be filled in with data at Publish time, making it easier to manage and manipulate content in ways that are not possible using standard T4 Tags without needing extensive coding expertise or familiarity with the complexities of Programmable Layouts.
One of the key features of Handlebars is its simplicity. With a syntax that closely resembles regular HTML, users can quickly grasp the basics and start building more "dynamic" Content types and Page layouts.
Handlebars uses double curly braces {{}}
to denote placeholders, which are then replaced with actual data when the layout is Published – much like the t4 tags you may be familiar with today.
The Terminalfour implementation of Handlebars comes with an extensive toolkit of "Helpers" to allow you to add logic to your layouts in a way that just isn't possible with t4 tags.
From Terminalfour 8.3.19 you can make use of Handlebars by selecting it as a processor type on your Page Layouts and Content Layouts:
Before we dive in...
8.3.19 is our initial release of Handlebars and we'll be extending the functionality and improving the experience over the next several releases of the platform.
Before we explore how Handlebars works it's important to mention a few items up front to help you make the best use of the feature.
Mixing t4 tags and Handlebars expressions
When setting the Content layout processor to Handlebars Content you can no longer use "T4 tags" in the layout. Instead you must use the handlebars helpers outlined in the rest of this guide.
Error handling
Like with standard T4 tag based layouts and programmable layouts it's possible to configure things incorrectly and get undesired or unexpected results.
Preview & Direct Edit
When an error is encountered with a Handlebars layout during Preview or Direct Edit we output an inline error message on the page to users.
This error is in the form of a table and displays the following info:
- The Section ID where the error is occurring
- The asset language
- The Content ID (if applicable)
- The error message
- The content layout name (if applicable)
- The layout code (if applicable)
This should give you enough information to find out where the problem exists so you can debug.
Example:
Publish
When a Publish happens and an error is encountered we could have done one of two things:
- We could ignore the error, and continue the Publish
- We could stop the publish to prevent breaking the live site
Both have their pros and cons and ultimately we'll need to hear from you, our users, about how you're using Handlebars to determine the best long term solution.
For now, we've taken the safest and least destructive option which is to fail the publish. This means if you accidentally introduce a breaking error in your most commonly used Content Type or Page Layout we'll prevent that error from getting pushed to your live site and ultimately breaking a significant portion of your web pages.
When the publish fails it does so with very clear messaging in the logs explaining the reason for the failure.
Example
Direct Edit
In the initial release of Handlebars, it does not support inline editing with Direct Edit.
However, the Handlebars feature was designed with Direct Edit in mind, and we aim to bring inline editing to an upcoming release of Terminalfour.
Before You Start
Be sure you have the following added to your training site:
1. Duplicate the "T205: Training Site Example (Duplicate Me)" into your Site Structure
2. Duplicate the "T205 Training Site Example (Duplicate Me)" Page layout
3. Create a "T205 Training Site Example" Channel
4. Duplicate the "T205 Training Site Example: General Content" Content Type
5. Duplicate the "T205 Training Site Example: News Item" Content Type
Let's also add some sample content using the "General Content" content type.
1. On the Site Structure screen, click on the name of your Home section.
2. The General information about this section screen appears, select the Content types tab.
3. Using the Filter feature, locate your content type.
4. Select the radio button to enable your content type for either the branch or section:
a. Enabled (branch): the Content type can be used in this section as well as all its sub-sections.
b. Enabled (section): the Content type can be used in this section only.
5. Click Save changes to confirm your selection. You can now use the "General Content" content type to add content to your section.
6. Add "General Content" to both the Home and About sections of your website. Feel free to use this Lorem Ipsum generator.
Back to top
1. Updating the Page Layout
In this example, you will learn how to update several t4 tags contained within the page layout. The page layout has been prepared to use the Handlebars Content layout processor. However, several t4 tags remain in the page layout.
- Let's learn how to replace any t4 tags that point to CSS and/or JavaScript files and any Navigation Object t4 tags with the appropriate Handlebars code.
Exercise 1.1: Replacing a t4 tag that references a CSS stylesheet in the media library
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- You will add the new Handlebars code below to the header code of the page layout.
- Click on the </> Header code tab.
- Let's replace the existing t4 tag which is used to reference a CSS file in the media library.
{{{media id="10858" layout="css/*"}}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 1.2: Replacing a t4 tag Link Menu Navigation Object that generates a navigation menu
- Replace the t4 tag Link Menu Navigation Object that generates the top navigation menu.
{{nav name="T201 Training Site Example: Main/Top Link Menu" id="258"}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 1.3: Replacing a t4 tag that references a JavaScript file in the media library
- Click on the </> Footer code tab.
- Replace the t4 tag that references the jQuery JavaScript file.
{{{media id="10861" layout="text/javascript"}}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
2. Updating the "General Content" Content Type
In this example, you will learn how to switch from using the T4 Tag Content layout processor to using the Handlebars Content layout processor.
- You will convert the T4 tags used in the General Content content type with the corresponding Handlebars code.
Exercise 2.1: Updating the content layout processor to use Handlebars
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- The Content layouts tab is an area to add Content Layout(s) for your Content Type. Click into the "text/html" default content layout to edit it.
- Click into the General information tab.
- Name: "text/html" - this is the default Type set in the Channel. This ensures the content can be displayed.
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click Save changes to save the changes to your Content Type.
- Update your preview to check the result.
Exercise 2.2: Replacing a t4 anchor tag with Handlebars code
- Click into the Content layouts tab.
- Select the "text/html" content layout and open the </> Content layout code tab.
- Replace the HTML anchor t4 tag. You can use the anchor helper to achieve this.
- Replace <t4 type="meta" meta="html_anchor" /> with the anchor helper.
{{anchor}}
<h2><t4 type="content" name="Heading" output="normal" modifiers="striptags,htmlentities" /></h2>
<t4 type="content" name="Main body" output="normal" modifiers="medialibrary,nav_sections" />
Do not use T4 tags to display the Header and Main body fields of the Content Type. Since you are using the Handlebars Content layout processor in this content layout you must use Handlebars code only as T4 tags will not work in this context.
Exercise 2.3: Replacing the "Heading" and "Main body" elements
- Replace the Heading and Main body elements to ensure these are displayed. You can use the publish helper to achieve this.
- Replace the Heading element with: {{publish element="Heading"}}
- Replace the Main body element with: {{publish element="Main body"}}
{{anchor}}
<h2>{{publish element="Heading"}}</h2>
{{publish element="Main body"}}
Exercise 2.4: Troubleshooting the "General Content" content type
- Let's preview the page to see how the content is being displayed. Notice how the content inside your main body element is being output to the page.
A key thing to note is that when using the publish helper it will not process any HTML and instead will output the HTML encoded equivalent by default. If you need to output the data as HTML (for example, if you're using a HTML element, or if it's a Plain text element being used to output "Code") then you would use triple curly braces {{{}}}
.
- Add the triple curly braces {{{ }}} to wrap your HTML "Main body" element.
{{anchor}}
<h2>{{publish element="Heading"}}</h2>
{{{publish element="Main body"}}}
3. Canonical URL
A canonical URL is the preferred version of a webpage's URL that you want search engines to index and prioritize. It helps avoid duplicate content issues when the same or similar content is accessible via multiple URLs.
Canonical URLs prevent duplicate content issues, they help search engines understand which version of a webpage should be considered the original thereby preventing SEO penalties for duplicate content. Also, by specifying a canonical URL, you ensure that all backlinks, page rank and other SEO signals are attributed to the preferred URL boosting SEO ranking.
- The canonicalURL helper is used to output a Canonical URL meta tag on the page.
- Usually this would be used to output a <link> tag in the <head> of your HTML.
- Your page layout currently is missing a Canonical URL, let’s add one to the page layout of your website.
Exercise 3.1: Adding a Canonical URL to the page layout
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- You will add the new Handlebars code below to the header code of the page layout.
- Click on the </> Header code tab.
- Copy the code below to your clipboard, and paste it into the Header code:<link rel="canonical" href="{{canonicalURL}}" />
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 3.2: Testing the Canonical URL using a mirrored section
- In your site structure mirror your "About" section into your "Life at T4U" section of your website.
- Click into the blue actions button of your "About" section and select Mirror branch. Then select your "Life at T4U" section in the pop-up modal.
- Preview the mirrored "About" section from your "Life at T4U" section. The Canonical URL should output a link referencing the original URL of the "About" section.
4. Page Titles
In this example, you will learn how to output custom page titles in the title tag of your page layout. You will look at a variety of different options to do this.
- You will learn how to use the sectionName helper to output the section name as the title of your page. Next, you will learn how to output a "Custom Page Title" by using a field from the SectionMetaDescription Content type.
- On fulltext pages, you will ouput a content element from the page layout.
- Finally, you will build logic into your code to output the appropriate title depending on whether the element is populated and whether you are in a fulltext page or not.
Exercise 4.1: Displaying the section name
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- Add the new Handlebars code below to the Header code of the page layout.
- Click on the </> Header code tab.
- Display the Section Name using the sectionName helper.
<title>{{sectionName}} - Terminalfour University</title>
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 4.2: Displaying a custom page title
In this example, you will use the section helper to output a "Custom Page Title". This field is configured in the SectionMetaDescription Content Type and is available within the General tab of your sections.
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- Add the new Handlebars code below to the Header code of the page layout.
- Click on the </> Header code tab.
- Display the "Custom Page Title" from the SectionMetaDescription Content Type.
<title>{{section field="Custom Page Title"}} - Terminalfour University</title>
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 4.3: Using the if/else block level helpers
- You can use the if helper to check if the SectionMetaDescription has a field called “Custom Page Title” and whether it is set to a value. If so, output the title tag with the name of the “Custom Page Title” field.
- Use the else helper for when the “Custom Page Title” field is not set, in which case, you can display the section name using the sectionName helper.
{{#if (section field="Custom Page Title")}}
<title>{{section field="Custom Page Title"}}</title>
{{else}}
<title>{{sectionName}} - Terminalfour University</title>
{{/if}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 4.4: Using the fulltext block level helper and displaying a content element in the page layout
Before You Start
Let's add some sample content using the "News Item" content type.
1. On the Site Structure screen, click on the name of your News section.
2. The General information about this section screen appears, select the Content types tab.
3. Using the Filter feature, locate your content type.
4. Select the radio button to enable your content type for either the branch or section:
a. Enabled (branch): the Content type can be used in this section as well as all its sub-sections.
b. Enabled (section): the Content type can be used in this section only.
5. Click Save changes to confirm your selection. You can now use the "News Item" content type to add content to your section.
The fulltext helper has both an inline and block level variant. It behaves differently depending on which is used.
The inline fulltext helper can be used to output a link to the fulltext page of a given content type. You will learn to use this variant in an upcoming exercise.
The fulltext block level helper, which you will use in this example, allows you to know if you are viewing a fulltext page.
- Let's add the fulltext block level helper to the code to determine whether you are in a standard or fulltext page.
Note that by adding the fulltext block level helper to the code in this instance, you are now also creating a nested if within your logic.
{{#fulltext}}
{{else}}
{{#if (section field="Custom Page Title")}}
<title>{{section field="Custom Page Title"}} - Terminalfour University</title>
{{else}}
<title>{{sectionName}} - Terminalfour University</title>
{{/if}}
{{/fulltext}}
- Let's update the code by outputting the Headline element within the title tag only when in a fulltext page.
Because you are in a fulltext page you have access to the elements of the Content Type which is something that isn't possible using T4 tags. This allows you to use the publish helper to output the Headline element of the fulltext content type.
{{#fulltext}}
{{#if (section field="Custom Page Title")}}
<title>{{section field="Custom Page Title"}} | {{publish element="Headline"}} - Terminalfour University</title>
{{else}}
<title>{{sectionName}} | {{publish element="Headline"}} - Terminalfour University</title>
{{/if}}
{{else}}
{{#if (section field="Custom Page Title")}}
<title>{{section field="Custom Page Title"}} - Terminalfour University</title>
{{else}}
<title>{{sectionName}} - Terminalfour University</title>
{{/if}}
{{/fulltext}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
6. Preview Helper
The preview helper allows you to output content only in Preview.
- You will learn how to use the preview helper to output the channel name, section name and publish URL when in preview.
Exercise 6.1: Using the preview helper
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- You will add the new Handlebars code below to the header code of the page layout.
- Click on the </> Header code tab.
- Let's use the preview helper to determine if we are in preview.
{{#preview}}
<p>You are in preview.</p>
{{else}}
<p>This is the published Page.</p>
{{/preview}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 6.2: Using the channelName, sectionName and publishURL helpers
- Display the channel name, section name and publish URL. Use the channelName, sectionName, and publishURL helpers to achieve this.
{{#preview}}
<p><strong>Channel name:</strong> {{channelName}}</p>
<p><strong>Section name:</strong> {{sectionName}}</p>
<p><strong>Publish URL:</strong> {{publishURL}}</p>
{{else}}
<p>This is the published Page.</p>
{{/preview}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 6.3: Linking to the publishURL from preview
- Add a link to the publishURL.
<p><strong>Publish URL:</strong><a href="{{publishURL}}"> {{publishURL}}</a></p>
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Exercise 6.4: Adding styling to the preview display
- Copy the code below into your page layout.
{{#preview}}
<div class="row">
<div class="small-12 columns text-left hide-for-small-only" >
<div class="panel callout">
<p><strong>Channel name:</strong> {{channelName}}</p>
<p><strong>Section name:</strong> {{sectionName}}</p>
<p><strong>Publish URL:</strong><a href="{{publishURL}}"> {{publishURL}}</a></p>
</div>
</div>
</div>
<style>
.panel.callout {
background-color: lightcyan;
border-color: darkblue;
margin-top: 1rem;
}
</style>
{{else}}
<div class="row">
<div class="small-12 columns text-left hide-for-small-only">
<div class="panel callout">
<strong>This is the published Page</strong>
</div>
</div>
</div>
<style>
.panel.callout {
background-color: lightcyan;
border-color: darkblue;
margin-top: 1rem;
}
</style>
{{/preview}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
5. Display Image Based on Element
In this example, you will learn how to provide a fallback image depending on whether an image element has been set. You will use the News Item Content Type and update the content layout with the Handlebars code required.
- If the image element of the Content Type is set, then display the image, otherwise display a default fallback image.
- You can use a simple ifSet helper to check if the image is set.
- You will also learn how to format dates using Handlebars.
Exercise 5.1: Updating the "text/html" content layout to use Handlebars
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- The Content Layout tab is an area to add Content Layout(s) for your Content Type. Click into the "text/html" content layout to edit it.
- Click into the General information tab.
- Name: "text/html" - this is the default Type set in the Channel. This ensures the content can be displayed.
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Content Layout code: this determines the output for your content. If you have created the HTML already, you can start by pasting that into the code field as displayed below.
Exercise 5.2: Updating the "text/html" content layout
- Click into the Content layouts tab.
- Select the "text/html" content layout and open the </> Content layout code tab.
- Replace the "Headline" element t4 tag only. You will replace the fulltext link in an upcoming exercise.
<h3>
<a href="<t4 type="content" name="Name" output="fulltext" use-element="true" filename-element="Headline" modifiers="striptags,htmlentities" />">
{{publish element="Headline"}}
</a>
</h3>
- Replace the "Release date" element t4 tag.
<em><strong>{{publish element="Release date"}}</em></strong>
- Replace the "Teaser" element t4 tag.
<p>{{publish element="Teaser"}}</p>
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 5.3: Creating the Fulltext link
In the previous exercise (Exercise 4.4: Using the fulltext block level helper), you learned how to use the block-level variant of the fulltext helper. To create a fulltext link, you can use the inline-level variant of the fulltext helper instead.
- Click into the Content layouts tab.
- Select the "text/html" content layout and open the </> Content layout code tab.
- To generate a fulltext link update the "Headline" element like so:
<h3>{{{fulltext linkText=(publish element="Headline")}}}</h3>
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 5.4: Formatting a date element
If you output a Date element using the publish Helper like this:
<em><strong>{{publish element="Release date"}}</em></strong>
You'd get an output in the following format (Standard ISO Date format):
Mon, 10 Sep 2024 11:35:00 IST
There is also a second helper called dateElement that works like so:
{{dateElement element="Date element"}}This will output in a slightly different format:
2024-09-20T09:30:10Z[Etc/UTC]The difference is that the dateElement helper outputs a date in such a format that can be accepted into the dateFormat helper. You can use the dateFormat helper to define a date format and pass in the dateElement helper (which provides the date in the required structure for the dateFormat helper to function).
Note that the dateFormat helper accepts two arguments: (dateToFormat and formatToUse)
{{dateFormat dateToFormat formatToUse}}
- Click into the Content layouts tab.
- Select the "text/html" content layout and open the </> Content layout code tab.
- Output the "Release date" element using the following code:
<em><strong>{{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma" }}</strong></em>
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 5.5: Updating the "text/fulltext" content layout to use Handlebars
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- The Content Layout tab is an area to add Content Layout(s) for your Content Type. Click into the "text/fulltext" content layout to edit it.
- Click into the General information tab.
- Name: "text/fulltext" - this is the default Type set in the Channel. This ensures the content can be displayed.
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Content Layout code: this determines the output for your content. If you have created the HTML already, you can start by pasting that into the code field as displayed below.
Exercise 5.6: Updating the "text/fulltext" content layout
- Click into the Content layouts tab.
- Select the "text/fulltext" content layout and open the </> Content layout code tab.
- Replace the "Headline" element t4 tag.
<h2>{{publish element="Headline"}}</h2>
- Replace the "Release date" element t4 tag. Make sure to add the correct formatting.
<em><strong>{{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma"}}</strong></em>
- Replace the "Image" element t4 tag.
<div class="newsimage">
{{{publish element="Image"}}}
</div>
- Replace the "Image caption" element t4 tag.
<div class="newsimage">
{{{publish element="Image"}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
</div>
- Replace the "Teaser" element t4 tag.
<div class="newsimage">
{{{publish element="Image")}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
</div>
{{publish element="Teaser"}}
- Replace the "News story" element t4 tag.
<div class="newsimage">
{{{publish element="Image")}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
</div>
{{publish element="Teaser"}}
{{{publish element="News story"}}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 5.7: Using the media and mediaId helpers
In this exercise, you will learn how to use the media and mediaId helpers to apply a different layout to the image in the content layout.
Note that when you output a Media element using the publish helper like you are doing here, the media element will be output using the standard media layout selected in the UI. If you needed to enforce a specific alternate Media layout you can use the mediaID helper alongside the media helper to do so.
For this example, you need to use the media helper to output a piece of Media with an explicit layout:
{{{media id="123" layout="image/alternative"}}}
You will then use the mediaId heper to pass in the id of your Image element to the media helper. It would work like so:
{{{media id=(mediaId element="Media element") layout="text/alternative"}}}
- Let's apply a different layout to the image in the content layout. In this example, you will use the alternate layout: "Image with caption".
<h2>{{publish element="Headline"}}</h2>
<em><strong>{{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma"}}</strong></em>
<div class="newsimage">
{{{media id=(mediaId element="Image") layout="Image with caption"}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
<div>
{{publish element="Teaser"}}
{{{publish element="News story"}}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 5.8: Displaying a fallback image and caption
- Click into the Content layouts tab.
- Select the "text/fulltext" content layout and open the </> Content layout code tab.
- The ifSet helper allows you to check whether the Image element is set and display the Image element if it is.
{{#ifSet element="Image"}}
{{{media id=(mediaId element="Image") layout="Image with caption"}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
- Otherwise if the Image element is not set, display a fallback image.
- You need to retrieve the id for the fallback image from the media library. In this example, you will use the image with id 10966 already in the media library.
{{else}}
{{{media id="10966"}}}
<div class="caption">
<p>This is a default caption.</p>
</div>
{{/ifSet}}
- Click Save changes to save the changes to your page layout.
- Update your preview to check the result.
Complete Code Listing:
<h2>{{publish element="Headline"}}</h2>
<em><strong>{{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma" }}</strong></em>
<div class="newsimage">
{{#ifSet element="Image"}}
{{{media id=(mediaId element="Image") layout="Image with caption"}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
{{else}}
{{{media id="10966"}}}
<div class="caption">
<p>This is a default caption.</p>
</div>
{{/ifSet}}
</div>
{{publish element="Teaser"}}
{{{publish element="News story"}}}
7. Working With Lists
In the following examples, you will learn how to work with lists and display them on the page. You will learn to use the selected and list helpers and the many different variables that can be used within lists in Handlebars.
- Generally when working with elements based off of lists you would loop over the elements in a list and decide your output.
- You will learn how to take the selected values from a list and output them as a HTML unordered lists (<ul>).
- In the following examples, you will focus on learning how to use the in-built helpers list and selected to work with lists.
Two in-built Helpers
There are two built in helpers for working with lists in Handlebars. The "list" helper and the "selected" helper.
List Helper
It allows you to loop over every item in a list. You have access to helpful variables that let you know whether the list item was selected by the user, whether there's a sublist, whether the list item is first or last, and many more. Check the docs for full information.
Selected Helper
The selected helper works in a very similar way but instead of looping over the whole list, it just loops over the selected items in the list.
The list and selected Helpers are both used in order to help with the output of List elements:
- Select Box
- Check Box
- Radio Button
- Multi-select List
- Multiple Select
- Cascading List
Both the list and selected Helpers are designed to be used alongside the built-in each block expression with handlebars.
Using the list helper as an example:
{{#each (list element="List Content Element")}}
<p>{{name}} - {{value}}</p>
{{/each}}
The above code is looping over every element in the list whether it is selected by the user or not and outputting the name and value in paragraphs.
However, there are a lot more variables available to use than just {{name}} and {{value}}. With both the list and selected helpers we have the following variables available to us:
- listId - The Id of the list that this entry belongs to.
- entryId - The Id of this list entry.
- name - The name of this list entry.
- value - The value of this list entry.
- sequence - The sequence of this entry in the list.
- language - The language of the list entry.
- selected - true if the list entry is selected, false otherwise.
- hasSubList - true if the entry contains a sub-list.
- subList - A reference to the sub-list, if one is present.
- subListId - the Id of the sub-list, if present.
In addition to the variables relating to each list entry returned, there are a number of variables made available to give the developer more information about the position of each entry in the list.
- @first - true if this is the first entry in the list/array.
- @last - true if this is the last entry in the list/array.
- @odd - true if this this entry has an odd index. Note that the array is zero-indexed.
- @even - true if this this entry has an even index. Note that the array is zero-indexed.
- @index - Returns the index of this entry within the list/array.
These allow us full control over how the lists should be output.
Using the selected helper
- Let's build an example where you will learn how to use the selected helper.
- In this example, you will use the selected helper and iterate not through the whole list but rather only through the selected items and display them.
Exercise 7.1: Adding a list element to the "General Content" content type
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- Select the Elements tab.
- Click the Add element button to add the new list select element as per the table below:
- Name: Give your List element a descriptive name. (e.g. "Select degree programs")
- Description: Give your List element a description.
- Type: Choose "Multi-select List".
- List used for values: Select "T205 Program Categories" from the available list options.
Name | Description | Type | Max Size | Use as filename | Required | Show |
---|---|---|---|---|---|---|
Select degree programs | Select the degree programs you are interested in. |
Multi-select List List used for values: T205 Program Categories |
leave default | N/A | Yes | Yes |
Exercise 7.2: Using the each and selected helpers
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- Click into the Content layouts tab.
- Choose to edit your "text/html" content layout.
- Use the each and selected helpers to iterate through the selected items in the list only.
{{#each (selected element="Select degree programs")}}
{{/each}}
Exercise 7.3: Using the @first variable
- Open an unordered list (<ul>) if in the first iteration of the loop. Use the if helper and the @first variable.
{{#each (selected element="Select degree programs")}}
{{#if @first}}
<ul>
{{/if}}
{{/each}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 7.4: Using the name variable of a list
- Output list items (<li>) with the name of each item in the list.
{{#each (selected element="Select degree programs")}}
{{#if @first}}
<ul>
{{/if}}
<li>{{name}}</li>
{{/each}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 7.5: Using the @last variable
- Use the if helper and the @last variable to close the unordered list.
{{#each (selected element="Select degree programs")}}
{{#if @first}}
<ul>
{{/if}}
<li>{{name}}</li>
{{#if @last}}
</ul>
{{/if}}
{{/each}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Using the list helper
- In this second example, let's use the list helper to display the whole list and additionally display the items that have been selected in bold.
Exercise 7.6: Using the list helper
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- Click into the Content layouts tab.
- Choose to edit your "text/html" content layout.
- Use the each and list helpers to iterate through all the items in the list.
- Open an unordered list (<ul>) if in the first iteration of the loop. Use the if helper and the @first variable.
{{#each (list element="Select degree programs")}}
{{#if @first}}
<ul>
{{/if}}
{{/each}}
Exercise 7.7: Using the selected helper
- Output an <li> tag for every value in the list. If the list item has been selected apply a <strong> tag to make it bold.
- Close the unordered list with a </ul> tag if in the last iteration. Use the if helper with the @last variable to achieve this.
{{#each (list element="Select degree programs")}}
{{#if @first}}
<ul>
{{/if}}
<li>
{{#if selected}}<strong>{{/if}}
{{name}}
{{#if selected}}</strong>{{/if}}
</li>
{{#if @last}}
</ul>
{{/if}}
{{/each}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
8. Embedding Content Layouts
In the following example, you will learn how to embed content layouts using the embed helper.
- You will learn how to output a different content layout based on what value a user has selected in a list.
- You will add a list element to choose a specific content layout to be applied to the News Item Content Type.
- The user can only choose a single item in the list (e.g. they're not using a Multi-select list or a Checkbox). You will then use the choice selected to output the corresponding layout.
Exercise 8.1: Creating the "Standard" content layout
- The "Standard" content layout will only output the "Headline", "Release date" and "News story" elements of the News Item content type.
- Go to Assets > Content Types.
- Click your Content Type name to edit it (Use the Filter tool to search).
- Open the Content layouts tab and click Add content layout.
- Fill in the General information tab.
- Name: "text/standard-layout".
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click into the Content layout code tab.
- Copy the code below as your "Standard" content layout code.
<h3>{{{fulltext linkText=(publish element="Headline")}}}</h3>
<em><strong>Release Date: {{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma" }}</strong></em>
{{{publish element="News story"}}}
- Click Save changes to save the changes to your content layout.
Exercise 8.2: Embedding the "Standard" content layout using the embed helper
- Update the "text/fulltext" content layout of the News Item Content Type. Use the embed helper to embed the "Standard" content layout you created in the previous exercise.
{{embed layout="text/standard-layout"}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 8.3: Adding a list element to the "News Item" content type
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search).
- Open the Elements tab.
- Click the Add element button to add the new list select element as per the table below:
- Name: Give the element a descriptive name.
- Description: Give your select list a description.
- Type: Choose "Select Box".
- List used for values: Select "T205 Content Layout Types" from the available list options.
Name | Description | Type | Max size | Use as filename | Required | Show |
---|---|---|---|---|---|---|
Content layout | Select a content layout to be used for this content. |
Select Box List used for values: T205 Content Layout Types
|
leave default | N/A | Yes | Yes |
Exercise 8.4: Adding the "Enhanced" content layout
- The "Enhanced" content layout will add the Teaser, Image and Image caption elements to the output.
- Go to Assets > Content Types.
- Click your Content Type name to edit it (Use the Filter tool to search).
- Open the Content layouts tab and click Add content layout.
- Fill in the General information tab.
- Name: "text/enhanced-layout".
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click into the Content layout code tab.
- Copy the code below as your "Enhanced" content layout code.
<h3>{{{fulltext linkText=(publish element="Headline")}}}</h3>
<em><strong>Release Date: {{dateFormat (dateElement element="Release date") "YYYY/MM/dd hh:mma" }}</strong></em>
<div class="newsimage">
{{#ifSet element="Image"}}
{{{publish element="Image"}}}
<div class="caption">
{{publish element="Image caption"}}
</div>
{{else}}
{{{media id="10966"}}}
<div class="caption">
<p>This is a default caption.</p>
</div>
{{/ifSet}}
</div>
{{publish element="Teaser"}}
{{{publish element="News story"}}}
- Click Save changes to save the changes to your content layout.
Exercise 8.5: Updating the "text/fulltext" content layout
- Use the each and selected helpers to retrieve the selected value in the list.
{{#each (selected element="Content layout")}}
There are a number of helpers to allow you to compare values:
eq - Tests if two values are equal
neq - Tests if two values are not equal
gt - Tests if one value is greater than another
gte - Tests if one value is greater than or equal to another
lt - Tests if one value is less than another
lte - Tests if one value is less than or equal to another
and - Tests if both values are true
or - Tests if either values are true
not - If the provided value is false then the block will not be processed
- You can use the eq helper to check the value of the list selected ("Standard Layout") and the embed helper to then embed the appropriate layout, "standard-layout", this must be the name of the content layout defined in the Content Type.
Arguments are space separated when passed to handlebars expressions (as opposed to comma separated).
{{#eq (publish element="Greeting") "Hello"}}
<p>Hello to you too!</p>
{{else}}
<p>You didn't say "Hello".</p>
{{/eq}}
{{#lt 5 8}}
<p>5 is indeed less than 8.</p>
{{else}}
<p>This will never be published because 5 is always less than 8.</p>
{{/lt}}
{{#each (selected element="Content layout")}}
{{#eq value "Standard Layout"}}
{{embed layout="text/standard-layout"}}
{{/eq}}
- You can use the eq helper to check the value of the list selected ("Enhanced Layout") and the embed helper to then embed the appropriate layout, "enhanced-layout", this must be the name of the content layout defined in the Content Type.
{{#each (selected element="Content layout")}}
{{#eq value "Standard Layout"}}
{{embed layout="text/standard-layout"}}
{{/eq}}
{{#eq value "Enhanced Layout"}}
{{embed layout="text/enhanced-layout"}}
{{/eq}}
{{/each}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
9. Wrapper Content Type
In this example, you will build an Accordion Content Type to learn how to work with sequences of content items of the same type.
- Allows a sequence of content items of the same type to be wrapped in markup.
- Used for sliders, accordions, tabs, card groups and other repeatable items.
first and last Helpers
The first Block level helper will be true when the content item is the first piece of content in a section.
{{#first}}
<h1>First content item in the section</h1>
{{/first}}The last Block level helper will be true when the content item is the last piece of content in a section.
{{#last}}
<footer>Last content item in the section</footer>
{{/last}}
firstOfType and lastOfType Helpers
These helpers let you know if an item of content is the first and last of its type in a section:
{{#firstofType}}
Only output if first of this content type in section
{{/firstOfType}}{{#lastOfType}}
Only output if last of this content type in section}}
{{/lastOfType}}
firstInSequence and lastInSequence Helpers
Perhaps more flexible though, are these helpers which allow you to determine if an item of content is the first and last of its type in an uninterrupted sequence of content in a section.
{{#firstInSequence}}
Only output if first of this content type in an uninterrupted sequence in this section
{{/firstInSequence}}
{{#lastInSequence}}
Only output if last of this content type in an uninterrupted sequence in this section
{{/lastInSequence}}
Let's build an example to demonstrate the use of these helpers. In the following example, you will build an accordion component that displays FAQs.
Exercise 9.1: Setting up the jQuery UI Library
The accordion component is generated using the jQuery UI Library. In order to use this library, you will need to upload three files into your media library and then target them using handlebars in your page layout. For this example, the files have been previously uploaded to the media library, let's learn how to reference them using handlebars in the page layout.
- Go to Content > Media Library.
- Click into "T205 Training Site Example" and then into Developer Assets.
- Click into the CSS and JavaScript folders to retrieve the corresponding ids of the required libraries.
- Go to Assets > Page Layouts.
- Click your page layout name to edit it. (Use the Filter tool to search). Open the </> Header code tab.
- Use the media helper to create the link to the jQuery UI CSS file.
{{{media id="10925" layout="css/*"}}} <!-- jQuery UI CSS-->
- Open the </> Footer code tab.
- Use the media helper to create the link to the jQuery UI file.
{{{media id="10926" layout="text/javascript"}}} <!-- jQuery UI JS -->
- Insert the jQuery script below to generate the accordion component.
<script>
$( function() {
$( "#accordion" ).accordion();
} );
</script>
- Click Save changes to save the changes to your page layout.
Exercise 9.2: Creating the "Accordion" content type
- Go to Assets > Content Types > Create content type.
- Fill in the General content type information:
- Name: enter a name here. This should suggest what type of content it is used for.
- Description: describe in more detail when to use this Content Type.
- Minimum user level: if you wish to restrict who can use this content type, you can set a level here. If content types are created in groups, a user must be a member of the group as well as meet the minimum user level criteria to use the Content Type.
- Enable direct edit: decide if direct edit can be used for this content type.
- Mark as eForm: If checked, this allows your Content Type to collect eForm data.
- Workflow: if relevant, enable a workflow for content created using this content type.
- Primary group: Select your group. This allows you to select the group which is permitted to use this content type. Click Toggle shared groups to share the content type with more than one group.
- Select the Elements Tab.
- Each content type has a Name element by default. This is used to name the content and is typically not displayed on the published site.
- Add the other elements you need by filling in the information as outlined in the table below. Click add element to begin filling in the details for each element.
- Once you have added all your elements, click Save changes. The Content Layout tab opens.
Name | Description | Type | Max Size | Required | Show |
---|---|---|---|---|---|
Section Heading | Optional section heading | Plain Text | 80 | No | Yes |
Section Description | Optional section description | Plain Text | 300 | No | Yes |
Accordion Heading | The heading/title of the accordion | Plain Text | 80 | Yes | Yes |
Accordion Body | The content of the accordion | HTML | 100000 | Yes | Yes |
Use the firstInSequence and lastInSequence helpers to ensure the accordions are surrounded appropriately with a wrapper div.
Exercise 9.3: Creating the "text/html" content layout
- Go to Assets > Content Types.
- Click your Content Type name to edit it. (Use the Filter tool to search). Open the Content layouts tab.
- Click into the Content layouts tab.
- Choose to edit your "text/html" content layout.
- In the Content layout code tab of your "text/html" content layout add the code as per below:
- Use the firstInSequence helper to embed the "text/before" content layout at the beginning of the accordion. Then embed your "text/middle" content layout. Finally, use the lastInSequence helper to embed the "text/after" content layout at the end of the accordion.
{{#firstInSequence}}
{{embed layout="text/before"}}
{{/firstInSequence}}
{{embed layout="text/middle"}}
{{#lastInSequence}}
{{embed layout="text/after"}}
{{/lastInSequence}}
Exercise 9.4: Creating the "text/before" content layout
- Go to Assets > Content Types.
- Click your Content Type name to edit it (Use the Filter tool to search).
- Open the Content layouts tab and click Add content layout.
- Fill in the General information tab.
- Name: "text/before".
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click into the Content layout code tab.
- Copy the code below as your "text/before" content layout code.
<h2>{{publish element="Section Heading"}}</h2>
<div id="accordion">
- Click Save changes to save the changes to your content layout.
Exercise 9.5: Creating the "text/middle" content layout
- Go to Assets > Content Types.
- Click your Content Type name to edit it (Use the Filter tool to search).
- Open the Content layouts tab and click Add content layout.
- Fill in the General information tab.
- Name: "text/middle".
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click into the Content layout code tab.
- Copy the code below as your "text/middle" content layout code.
<h3>{{publish element="Accordion Heading"}}</h3>
<div>{{{publish element="Accordion Body"}}}</div>
- Click Save changes to save the changes to your content layout.
Exercise 9.6: Creating the "text/after" content layout
- Go to Assets > Content Types.
- Click your Content Type name to edit it (Use the Filter tool to search).
- Open the Content layouts tab and click Add content layout.
- Fill in the General information tab.
- Name: "text/after".
- File Extension: Default - unless this is used with a different File Extension. This requires other extensions being permitted in the Channel.
- Syntax Type: HTML/XML – this determines which syntax is highlighted.
- Content layout processor: Update the content layout processor to Handlebars Content.
- Click into the Content layout code tab.
- Copy the code below as your "text/after" content layout code.
</div> <!-- close #accordion -->
<div>
<a href="#" class="button">Collapse All</a>
<a href="#" class="button">Expand All</a>
</div>
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.
Exercise 9.7: Updating the "text/html" content layout
Because this is so much shorter and easier to work with than the Programmable layout equivalent you should consider avoiding embedding alternate layouts altogether to improve performance and instead, do something like:
{{#firstInSequence}}
<h2>{{publish element="Section Heading"}}</h2>
<div id="accordion">
{{/firstInSequence}}
<h3>{{publish element="Accordion Heading"}}</h3>
<div>{{{publish element="Accordion Body"}}}</div>
{{#lastInSequence}}
</div> <!-- close #accordion -->
<div>
<a href="#" class="button">Collapse All</a>
<a href="#" class="button">Expand All</a>
</div>
{{/lastInSequence}}
- Click Save changes to save the changes to your content layout.
- Update your preview to check the result.