Built-in Helpers

Templating helper functions available out of the box

Introduction

Tapcart supports a handful of built-in helper functions that can be used to build out a block. These helpers are available out of the box, so no setup is needed beyond using the proper syntax.

registerEventHandler

By using the registerEventHandler helper function, you can update your variables, should their values change in real-time. Examples of this would be if a user signs in/out (thus changing the user variables), or if a product is added to the cart (thus changing the cart variables).

Handlebars.registerHelper('json', function(context) {
    return JSON.stringify(context,null,2);
});

const source = `
  <div>the Variables Test Block</div>
  <pre style="white-space:pre-wrap;word-break:break-all;">{{json this}}</pre>
`

let extraDiv = document.querySelector("#extra");
let extraTemplate = Handlebars.compile(source);
extraDiv.innerHTML = extraTemplate(Tapcart.variables)

Tapcart.registerEventHandler("product/updated", function(eventData) {
  Handlebars.compile(source);
  extraDiv.innerHTML = extraTemplate({...Tapcart.variables,...eventData})
  Tapcart.actions.showToast({
    type: "success",
    message: "Event occurred: \"product/updated\""
  })
});
Tapcart.registerEventHandler("customer/updated", function (eventData) {
  Handlebars.compile(source);
  extraDiv.innerHTML = extraTemplate({...Tapcart.variables,...eventData});
  Tapcart.actions.showToast({
    type: "success",
    message: "Event occurred: \"customer/updated\""
  })
});
Tapcart.registerEventHandler("cart/updated", function (eventData) {
  Handlebars.compile(source);
  extraDiv.innerHTML = extraTemplate({...Tapcart.variables,...eventData});
  Tapcart.actions.showToast({
    type: "success",
    message: "Event occurred: \"cart/updated\""
  })
})

if

The if helper allows you to conditionally render a block if the argument is true. If the argument returns false, null, undefined, "", 0, or [], then the block will not render. You can specify an alternative response for when the if clause returns false by using else.

<div class="user">
{{#if signedIn}}
<h1>Hello {{firstName}}</h1>
{{/if}}
</div>

The includeZero=true option may be set to treat the conditional as not empty. This effectively determines if 0 is handled by the positive or negative path.

{{#if 0 includeZero=true}}
<h1>Does render</h1>
{{/if}}

unless

The unless helper is essentially the opposite of if and can be used to test a negative conditional. Unless will render the block only if the argument returns a false value. It also supports else to specify what to do if the argument does not return a false value.

<div class="user">
{{#unless signedIn}}
<h1>PLease Sign In</h1>
{{/unless}}
</div>

each

The each helper allows you to iterate through a list. Within the block, this acts as a placeholder for the element in the iteration.

<ul class="orders_list">
  {{#each orders}}
    <li>{{this}}</li>
  {{/each}}
</ul>

with

The with helper allows you shift the evaluation context for a section of a template

{{#with name}}
{{firstname}} {{lastname}}
{{/with}}

when used in this context

{
  person: {
    firstname: "Kenyon",
    lastname: "Brown",
  },
}

will return:

Kenyon Brown

lookup

The lookup helper allows you to access values within a dictionary or array using the key of the dictionary or the index of the array

{{#each customer}}
   {{.}} lives in {{lookup ../cities @index}}
{{/each}}

The example above iterates over the customer array and for each index of the customer array it fetches the value at that index position from the locations array

How to build your own helpers

If you are not seeing the helpers you need, you can use handlebars.js to build your own helpers. You can leverage the Javascript below to implement Handlebars.js in the Javascript tab of the Custom Blocks text editor.

const vars = {customData: "hello world"}
const handlebarsSourceHTML = `<div>{{customData}}</div>`
const customTemplate = Handlebars.compile(handlebarsSourceHTML);
const parentDiv = document.querySelector("#customHandlebarsParentDiv");
parentDiv.innerHTML = customTemplate(vars);