Skip to content

Instantly share code, notes, and snippets.

@gurdiga
Last active December 23, 2015 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gurdiga/6697941 to your computer and use it in GitHub Desktop.
Save gurdiga/6697941 to your computer and use it in GitHub Desktop.
Handlebars to emulate Rails partials with locals

Handlebars to emulate Rails partials with locals

I’ve created a little helper that takes a partial name and a Ruby-like hash of parameters that will be passed into that partial:

Handlebars.registerHelper('include', function(partialName, options) {
  var locals = options.hash,
      context = this;

  // the included partial also inherits the current context’s data
  for (var property in context) {
    if (property in data) return;

    data[property] = context[property];
  }   

  // it’s called with a block
  if ('fn' in options) data['yield'] = options.fn(data);

  var templateCode = document.querySelector('#' + partialName).innerHTML;

  return new Handlebars.SafeString(
    Handlebars.compile(templateCode)(data)
  );  
});

The key thing here is that Handlebars helpers accept a Ruby-like hash of arguments. In the helper code they come as part of the function’s last argument—options— in its hash member. This way you can receive the first argument—the partial name—and get the data after that.

It returns a Handlebars.SafeString from the helper or use “triple‑stash”—{{{— to prevent it from double escaping.

One other nice thing is that helper can also be passed a Ruby-like block, and the block will inherit the data context of the parent. The block content is injected in the included partial as the variable yield, again, as in Ruby. One thing to note is that it’s output is not a SafeString so you should use “tripple-stash” like this: {{{ yield }}}.

Here is a more or less complete usage scenario:

<script id="text-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="text" id="{{id}}"/>
</script>

<script id="checkbox-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="checkbox" id="{{id}}"/>
</script>

<script id="form-template" type="text/x-handlebars-template">
  <form>
    <h1>{{title}}</h1>
    {{{ yield }}}
  </form>
</script>

<script id="form" type="text/x-handlebars-template">
  {{#include 'form-template' }}
    {{ include 'text-field' label="First name" id="author-first-name" }}
    {{ include 'text-field' label="Last name" id="author-last-name" }}
    {{ include 'text-field' label="Email" id="author-email" }}
    {{ include 'checkbox-field' label="Private?" id="private-question" }}
  {{/include }}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment