The recent Meteor 0.8 update featured Blaze, a complete rewrite of Meteor’s UI system. And with Blaze came along Spacebars, a replacement for Handlebars, the templating language Meteor was previously using.

Spacebars and Handlebars share the same syntax, but Spacebars brings quite a few Meteor-specific innovations. In this article, we’ll take a look at a few of these time-saving techniques, including:

  • Creating custom helpers.
  • Using JavaScript objects as arguments.
  • Dealing with HTML attributes.
  • Building custom block helpers.

Let’s get started!

Custom Helpers

This isn’t new to Spacebars, but it’s worth pointing out because it can make your code much more concise. Let’s say you’re storing your document’s timestamp in a createdAt property, and you want to format it in a human-readable format.

You could write a simple helper:

Template.profile.helpers({
  createdAtFormatted: function () {
    return moment(this.createdAt).format('MM/DD/YYYY, HH:MM');
  }
});

And then use it inside your template:

<template name="profile">
  <h3>{{name}}</h3>
  <h4>{{createdAtFormatted}}</h4>
  <p>{{bio}}</p>
</template>

This works great, but you might need to format multiple timestamps across your app, thus leading to duplicated template helpers. So instead, let’s create a custom formatTime helper:

UI.registerHelper('formatTime', function(context, options) {
  if(context)
    return moment(context).format('MM/DD/YYYY, hh:mm');
});

And invoke it right from your template:

<template name="profile">
  <h3>{{name}}</h3>
  <h4>{{formatTime createdAt}}</h4>
  <p>{{bio}}</p>
</template>

Note that the Handlebars.registerHelper function has now become UI.registerHelper, the Handlebars namespace being deprecated.

Objects as Arguments

Here’s another useful pattern: you can create and pass JavaScript objects as a helper’s arguments. For example, let’s consider the following JavaScript object:

myObject = {
  firstName: "John",
  lastName: "Smith"
}

Thanks to Spacebars, you can create that object and pass it as argument right from inside your helper tag:

<template name="profile">
  <h4>{{formatName firstName="John" lastName="Smith"}}</h4>
</template>

What’s more, this also works when passing arguments in a template include. In that case, the resulting object will be used as the template’s data context:

<template name="dashboard">
  <h4>{{>profile name="John Smith" email="john@gmail.com"}}</h4>
</template>

This can be a great way to reuse the same templates to display both static and dynamic content.

Smarter Attributes

Spacebars also makes dealing with HTML tags attributes much cleaner. For example, let’s say you need to find out if a checkbox is checked. You can write something like:

<input type="checkbox" checked="{{isChecked}}" />

If isChecked is true, you’ll get a checked checkbox as expected. But an additional benefit is that if isChecked is false, null, or undefined, Meteor will also remove the checked attribute altogether.

But where Spacebars really shines when it comes to handling attributes is with dynamic attributes. Just write:

<input {{attributes}} />

And have the helper return a JavaScript object:

Template.myTemplate.helpers({
  attributes: function () {
    return {
      name: "myName",
      class: "myClass anotherClass",
      value: 123
    }
  }
});

Spacebars will then automatically map out the object to the tag’s attributes:

<input name="myName" class="myClass anotherClass" value="123" />

This is a great way of simplifying your code, by merging multiple helpers into a single one.

Content Blocks

Another cool new Spacebars feature is content blocks. Using the special UI.contentBlock keyword, you can now easily define block helpers that are perfect for simple layouts or wrappers.

For example, let’s build a block helper that will let us quickly generate the markup required for a table. First, we’ll create a template that includes the UI.contentBlock keyword:

<template name="tableWrapper">
  <table>
    <thead>
      <tr>
        <td>Name</td>
        <td>Email</td>
      </tr>
    </thead>
    <tbody>
      {{> UI.contentBlock}}
    </tbody>
  </table>
</template>

We can now use our newly created block helper in another template (we’ll assume we already have another tableRow template that contains the markup for each row):

<template name="dashboard">
  {{#tableWrapper}}
    {{#each customers}}
      {{> tableRow}}
    {{/each}}
  {{/tableWrapper}}
</template>

But wait, there’s more! It turns out you can also pass a data context as a custom block helper’s argument.

We can use this in combination with the arguments syntax we saw earlier to pass an ad-hoc data context to our helper:

<template name="dashboard">
  {{#tableWrapper heading="Customers" footer="Most recent data available."}}
    {{#each customers}}
      {{> tableRow}}
    {{/each}}
  {{/tableWrapper}}
</template>

All that’s left is to then call that data context from within the block helper to add a heading and footer to our table wrapper:

<template name="tableWrapper">
  <h2>{{this.heading}}</h2>
  <table>
    <thead>
      <tr>
        <td>Name</td>
        <td>Email</td>
      </tr>
    </thead>
    <tbody>
      {{> UI.contentBlock}}
    </tbody>
  </table>
  <p>{{this.footer}}</p>
</template>

The result is a reusable, lightweight component (styled here using the Bootstrap 3 package):

The output of our HTML table block helper.

Note that for more complex layouts, you can also check out Iron Router’s Blaze-Layout.

Wrapping Up

I hope you’ve enjoyed this quick primer on Spacebars. And if you know any other useful patterns, leave a comment to let us know!