Introducing ICanHandlebarz.js – ICanHaz.js, meet Handlebars.js

I am currently working on a project that’s using “ICanHaz.js”:https://github.com/HenrikJoreteg/ICanHaz.js and “Mustache.js”:https://github.com/janl/mustache.js/ as a templating solution.  While I appreciate the logicless-templating paradigm that Mustache is built around, I quickly found that there were some problems in our application that just couldn’t be solved cleanly with the existing Mustache implementation:

* No scoping mechanism
* Undefined whitespace behavior

An hour or two poking around on google revealed “Handlebars.js”:https://handlebarsjs.com/, which attempts to solve the major problems we encountered. While Handlebars.js has some extra features that I feel deviate slightly from the concept of “Logicless” Templating (see Advanced Usage after the jump), you can get by just fine without them.

During my preliminary testing, I found that I missed the ease of having ICanHaz.js wrapping all my templates, so I melded Handlebars.js into the nice ICanHaz.js framework and created ICanHandlebarz.js.

h2. Basic Usage

ICanHandlebarz.js is mostly directly interchangeable with ICanHaz, with changes necessary only where Handlebars’ behavior differs from Mustache’s.

To add a Handlebars template to a webpage, you just need to include it in your HTML. ICanHandlebarz.js scans the document on load for anything with script type text/html and an id tag, compiles it, and attaches a function to trigger it to the global object “ich”.

<script id="villainprofile" type="text/html">
    <div class="villain-profile">
        <div class="name">Name: {{realName}}</div>
        <div class="alias">Alias: {{alias}}</div>
        <div class="powers">Powers: {{superPowers}}</div>
    </div>
</script>

You can then actually make use of this template anywhere in your javascript, just by calling ich.villainprofile. For example, using jQuery, we can create a villain within an existing DOM element.

var villain = {
  realName: "Ronald McDonald",
  alias: "Mickey D",
  powers: "The fry frazzler"
}
$('#villain').html(ich.villainprofile(villain));

This will stuff the templated data into the #villain element of the DOM.

h2. Paths

To fix the scoping issues present in Mustache, Handlebars introduces a concept of paths. Paths look and function much like relative filesystem paths. For example, if you need to print a link that has both a parent and child ID in it, you could use something like this.

<script id="accomplices" type="text/html">
    <div class="accomplice-list">Known Accomplices:
    {{#accomplices}}
        <div class="accomplice">
            <a href="/api/{{../id}}/accomplice/{{id}}" class="accomplice-link">
                <div class="accomplice-alias">Alias: {{alias}}</div>
                <div class="accomplice-description">Description: {{description}}</div>
            </a>
        </div>
    {{/accomplices}}
    </div>
</script>

h2. Advanced Usage

ICanHandlebarz.js supports most Handlebars.js features, including Partials and Helpers. The use of partials is exactly the same as it is for ICanHaz.js, so I’ll concentrate on Helpers, which are new in Handlebars.js.

Helpers allow you to register a function that will process data before it is displayed. This is the part of Handlebars that really deviates from the “Logicless” ideas of Mustache, but it can be extremely handy. As an example, ASP.net DateTimes serialize to a string format that uses unix time. This is all well and good, but very rarely would I care to directly inject a unix time into an HTML page. This is where helpers come in.

We’ll use a helper called “dateformat” to format an ASP.net date that we receive from some API. To keep consistency with ICH Partials and Templates, the helper function lives in the HTML document and is bound as a Handlebars helper at page load. Because of this, the function arguments live as a comma-separated string in a meta argument called “data-args”, and the function body lives within script tags.

<script id="lastModified" type="text/html">
    <div class="modified-date">This page last modified on {{{dateformat aspDate}}}</div>
</script>

<script id="dateformat" class="helper" data-args="aspDate" type="text/html">
//<![CDATA[ // Optional if there are no &, <, or > in your javascript.
      aspDateString = aspDate.toString()
      var dateObject = new Date(parseInt(aspDateString.substr(6)));
      return (dateObject.getMonth()+1) + '/' + dateObject.getDay() + '/' + dateObject.getFullYear();
//]]>
</script>

h2. More Info

ICanHandlebarz.js is capable of much more. Check out the “Handlebars.js”:https://handlebarsjs.com/ and “ICanHaz.js”:https://github.com/HenrikJoreteg/ICanHaz.js websites for a good intro to both of the primary components, and you’ll have a pretty good foundation for starting out with ICanHandlebarz. ICanHandlebarz should support all the features of Handlebars, although block helpers have not been extensively tested.

Check out the project on “Github”:https://github.com/atomicobject/ICanHandlebarz.js

Conversation
  • Hey, this is pretty cool. Maybe I should add “official” support for either to ICH?

    • Mitchell Johnson Mitchell Johnson says:

      If you’d like to add Handlebars support to ICH, that’d be awesome. I haven’t been doing much work with Javascript recently, but on this project, the Handlebars.js extensions were immensely helpful.

      The ICanHandlebarz.js implementation could probably use some cleanup, but it would certainly be a decent starting point.

    • Paul Stuart says:

      We can haz one unified goodness!?

  • Chandu says:

    Looks interesting.
    Am planning to move from MustacheJs/ICanHaz to HandelBars/ICanHandlebarz. When I check the GitHub repo, the last activity was about an year ago. Just wanted to check if the current version is production ready?

    • Mitchell Johnson Mitchell Johnson says:

      I don’t know of anyone who’s used ICanHandlebarz.js in a production project as of yet, and it’s been in my queue of things to catch back up on. If you’re considering the switch, I’d encourage you to make the change. If you take a look at the few commits that were necessary to do the original implementation, there’s not a whole lot of maintenance burden above and beyond ICanHaz.js.

  • Comments are closed.