This tutorial is part of a series on building a Zendesk Sell app:

In the previous tutorials, you created starter files for an app named Related Leads and modified the HTML file that's iframed into Zendesk Sell. Aside from the footer, the app so far only displays placeholder values. In this tutorial, you'll create templates to display data in the app's user interface (UI).

Templates are typically the building blocks of an app's user interface. They define different states, or views, for an application. For example, one template can contain an HTML form for entering search terms, and another template can dynamically list the search results.

This tutorial covers the following tasks:

  1. Adding a templating engine
  2. Creating a template to display organization information
  3. Inserting the template in your app
  4. Creating a template for error messages

Adding a templating engine

You can use any templating engine and whatever version you like with your apps. This app uses Handlebars.js.

  • Import the Handlebars library into your app by inserting the following <script> tag in iframe.html before the <script> tag that references your main.js file:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars.min.js"></script>

Creating a template to display organization information

Based on the design requirements in Planning the app, the app requires a template to display the following data:

  • The organization's name
  • A list of new leads for the organization

In Handlebars, you can define templates by including them in <script> tags.

To create the template

  1. In iframe.html, add the following organization template <script> tag before the other <script> tags:

    <script id="org-template" type="text/x-handlebars-template">  <h2>New leads for {{orgName}}</h2>  <ul>    {{#each leads}}      <li><a href="{{url}}" target="_blank">{{name}}</a></li>    {{/each}}  </ul></script>

    This template contains several Handlebars expressions. A Handlebars expression typically consists of a variable inside double curly braces. For example: {{name}}. When it runs, the app will replace these expressions with values from a Javascript data object. For the organization template, this object should contain:

    • The organization's name ({{orgName}})
    • An array of new leads ({{leads}}) for the organization. Each item in the array is an object. Each object in the array should contain:
      • The URL of the Lead page for the lead ({{url}})
      • The lead's full name ({{name}})

    The template also uses an {{#each}} helper to add a list item for each lead in the leads array.

  2. Enclose the <h2> and <ul> tags with {{#if}}...{{else}} helpers (highlighted):

    <script id="org-template" type="text/x-handlebars-template">  {{#if leads}}    <h2>New leads for {{orgName}}</h2>    <ul>      {{#each leads}}        <li><a href="{{url}}" target="_blank">{{name}}</a></li>      {{/each}}    </ul>  {{else}}    <h2>No new leads found for {{orgName}}.</h2>  {{/if}}</script>

    If an organization doesn't have any new leads, the list in the UI will be blank. To create a better user experience, the {{#if}}...{{else}} helpers hide the list and display an alternative heading if there are no new leads for the organization.

  3. Save iframe.html.

If you refresh the app, it doesn't change. You haven't inserted the template in the HTML yet. The next step is to insert the template and confirm that it works.

Inserting the template in your app

You insert templates into an element of your choice in the document. You add a <div> tag in your HTML file for inserting templates at runtime. Only one template at a time can be inserted, but you can switch to a different template. For example, you can start by displaying the splash page and then switch to another page after the user clicks a button.

  1. In iframe.html, delete the following tags:

    <h2>New leads for the organization</h2><ul>  <li><a href="" target="_blank">Lead one</a></li>  <li><a href="" target="_blank">Lead two</a></li></ul>
  2. Replace the deleted tags with the following:

    <div id="content"></div>
  3. In main.js, add the following displayLeads() function call (highlighted) to the self-invoking function:

    (function () {  const client = ZAFClient.init();  client.invoke("resize", { width: "100%", height: "150px" });  displayLeads();})();
  4. Add the displayLeads() function definition after the self-invoking function:

    function displayLeads() {  const orgData = {    orgName: "XYZ Widget Co.",    leads: [      {"name": "Alice Aragorn", "url": "https://app.futuresimple.com/leads/2104416001" },      {"name": "Bob Baggins", "url": "https://app.futuresimple.com/leads/2104416001" },    ]  };
      renderTemplate("org-template", orgData, "content");}

    In the first part of the function, the orgData object defines hard-coded values to pass to the Handlebars template. You'll later replace these values with live data from an API.

    The second part contains a call to the renderTemplate() function. This function passes data to the template and renders the template as HTML. It requires three arguments:

    • The ID of the <script> tag iframe.html that contains the template ("org-template")
    • The data object to pass to the template (orgData)
    • The ID of the tag in iframe.html that'll contain the rendered HTML ("content")
  5. Add the renderTemplate() function definition directly after the displayLeads() function definition:

    function renderTemplate(templateId, dataObject, divId) {  const source = document.getElementById(templateId).innerHTML;  const template = Handlebars.compile(source);  const compiledHtml = template(dataObject);  document.getElementById(divId).innerHTML = compiledHtml;}
  6. Save iframe.html and main.js. To review your changes, click the refresh icon.

    If your ZCLI server is not already running, see Testing the app in part 2 of this series.

    Handlebars sets the HTML content of the <div id="content"> tag in the iframe.html file:

Creating a template for error messages

If the app encounters a problem retrieving an organization's leads or other data, you want the user to see an error message about what went wrong.

  1. In iframe.html, add the following error template after your org-template script tag:

    <script id="error-template" type="text/x-handlebars-template">  <p>{{status}} - {{statusText}} error. Please report a bug at the link below.</p></script>

    The template will display an HTTP status error message, such as "404 - Not found error".

  2. In main.js, add the following function to render the template:

    function displayError() {  const errorData = {    'status': 404,    'statusText': 'Not found'  };
      renderTemplate("error-template", errorData, "content");}
  3. Call the displayError() function (highlighted) from your self-invoking function:

    (function () {  const client = ZAFClient.init();  client.invoke("resize", { width: "100%", height: "150px" });  displayLeads();  displayError();})();
  4. To test it, comment out displayLeads(); with double forward-slashes, save main.js and iframe.html, and then refresh the app.

    Similar to the organization template, Handlebars inserts the values of your errorData object into the error template and generates the final HTML. The app then sets as the HTML content of the <div id="content"> tag in iframe.html.

If you're moving to the next tutorial, you can leave the ZCLI server running. If you're done for this session, you can shut down the server by switching to your command-line interface and pressing Ctrl+C.

In the next tutorial, you'll learn how to get an organization's data using the Sell APIs. Continue to Part 4 - Getting data.