Sunday, 11 August 2013

Musings about MustacheJS

Let's say you have an array of user data in JSON format. In your webapp, you want to display each user as a nicely formatted HTML block. You also want to make the whole thing dynamic and Ajax-y, giving the option to edit/delete/create users. It would have to look something like this (but then nicely formatted):

USER 1
name, location
[delete] [edit]
USER 2
name, location
[delete] [edit] ...

Formatting/rendering your elements in JavaScript is then a logical thing to do. In this post I compare jQuery rendering to MustacheJS rendering and talk about the pros and cons of each.

jQuery rendering
Rendering the elements using jQuery is what most people are familiar with, but it can get messy for complex elements. Click here for a Fiddle displaying the situation. I created a HTML template for the element and placed it into a script tag, then in the render function I had to find each field by classname, and apply the formatted data value to the field. It works, but the render function can get quite long and unorganized, and the HTML template fills up with arbitrarily chosen classnames.

Moreover, our user record has sub-lists like 'labels for each user'. For each 'label' sub-element I again created a template in a script tag, created a JavaScript loop over the data-elements to render the sub-template, etc. This makes the rendering function looking even less tidy, and my previously clean template is now divided over two script tags. Imagine the mess when the elements become even more complicated.

MustacheJS
Enter MustacheJS: a 5kb minified JS library, designed to assist in exactly this problem: client-side rendering of JSON data structures, into HTML specified by a template. It has nice features such as:
  • Specifying where the data should be put using "Mustache" tags {{username}}, with field names corresponding to the JSON field names, so no more fuzzy class names to identify where the data should go
  • Easy to change the {{ tags to [[ tags, to solve conflict with Django template tags
  • Tags to specify a sub-part of the template should be repeated, solving the userlabels problem
  • If-then-else tags for some more complicated renderings (documentation)
Using Mustache, my rendering function was reduced to one line, and my template was again neatly clean and contained within one script element.
Click here for the improved rendering with Mustache

The pros
So do I recommend working with Mustache? Yes: it's small, and it doesn't get in the way: you can still solve things differently if you have to. And it definitely makes life easier and code tidier in many cases.

The cons
Working with Mustache a bit longer now, however, there are some things that you have to be aware of:
  • Client-side formatting: If you have for example a date in UnixTime format: 7892799393, then that is exactly how Mustache will render it. Of course you want to convert it into some human-readable value first. Your options are:
    • Use Mustache lambda functions for formatting. This is actually neat.
    • Add the formatted values to the JSON object server-side. It can become messy if there will be a lot of different formatting, eg. at some point I was stuck with 4 different date formats.
    • Switch to the Mustache-compatible HandleBars and use helper functions. (I didn't try it yet, because the tags conflict with Django too and changing them is not so easy as in Mustache
    • Use Mustache helper functions; have to look into this.
  • Even with the if-then-else-logic, it cannot always do all the magic you'd want to do during the rendering step. My answer to this: after Mustache rendering I parse the HTML into a jQuery object and do some more complex modifications before placing the element into the DOM. Still clean code, more functionality.
  • If you are formatting forms, Mustache cannot help you to get the values out of the form again. This is called two-way-data-binding. I'm still looking for alternative libraries that can do that; currently looking into AngularJS, which looks however like a bit of a too big hammer for such a simple nail, leading to some collateral head-aches about which I will muse later.
  • MustacheJS doesn't make you look as awesome as Magnum, PI. Only a real mustache can do that.
Until next time, fabulous followers!

No comments:

Post a Comment