"Else equals" in Handlebars (in SendGrid's Dynamic Templates)

Published on in Handlebars and SendGrid

There's a way to do an "else equals" check in Handlebars (in SendGrid's Dynamic Templates), though it's undocumented and a bit tricky.

Table of contents

Context

Problem

I wanted to do something like this:

{{! Pseudo code, doesn't work }}

{{#if locale == 'en'}}
  <h1>New article: {{articleNameEn}}</h1>
{{else if locale == 'sv'}}
  <h1>Ny artikel: {{articleNameSv}}</h1>
{{else}}
  <h1>Uusi artikkeli: {{articleNameFi}}</h1>
{{/if}}

But it wasn't quite that simple.

Solution

Step by step

  • Handlebar's #if helper checks only the truthiness of a value; you can't use == or other operators, so {{#if locale == 'en'}} is invalid.
  • You can create custom Handlebars helpers. However, when using Handlebars in SendGrid, you are limited to SendGrid's Handlebars helpers.
  • Luckily SendGrid provides an #equals helper:
    {{#equals locale 'en'}}
      <h1>New article: {{articleNameEn}}</h1>
    {{else}}
      <h1>Uusi artikkeli: {{articleNameFi}}</h1>
    {{/equals}}
    
  • But whoops, Handlebars helpers create new scopes, so {{articleNameEn}} and {{articleNameFi}} are "empty." Need to use the @root keyword:
     {{#equals locale 'en'}}
    -  <h1>New article: {{articleNameEn}}</h1>
    +  <h1>New article: {{@root.articleNameEn}}</h1>
     {{else}}
    -  <h1>Uusi artikkeli: {{articleNameFi}}</h1>
    +  <h1>Uusi artikkeli: {{@root.articleNameFi}}</h1>
     {{/equals}}
    
  • And how to do "else equals"? The documentation doesn't tell. But "else if" is documented, so let's try to imitate that:
    {{#equals locale 'en'}}
      <h1>New article: {{@root.articleNameEn}}</h1>
    {{else equals locale 'sv'}}
      <h1>Ny artikel: {{@root.articleNameSv}}</h1>
    {{else}}
      <h1>Uusi artikkeli: {{@root.articleNameFi}}</h1>
    {{/equals}}
    
    This code is syntactically valid and almost works:
    • If locale is 'en', the first branch is executed.
    • But if locale is 'sv', the third branch is executed. So the second branch ("else equals") is never executed.
  • Aha! Same gotcha as above. Because Handlebars is so eager to create new scopes, need to use the @root keyword here as well:
     {{#equals locale 'en'}}
       <h1>New article: {{@root.articleNameEn}}</h1>
    -{{else equals locale 'sv'}}
    +{{else equals @root.locale 'sv'}}
       <h1>Ny artikel: {{@root.articleNameSv}}</h1>
     {{else}}
       <h1>Uusi artikkeli: {{@root.articleNameFi}}</h1>
     {{/equals}}
    

Final code

{{#equals locale 'en'}}
  <h1>New article: {{@root.articleNameEn}}</h1>
{{else equals @root.locale 'sv'}}
  <h1>Ny artikel: {{@root.articleNameSv}}</h1>
{{else}}
  <h1>Uusi artikkeli: {{@root.articleNameFi}}</h1>
{{/equals}}