Transforming Handlebars

I’m in the process of shifting an application from server-side JSP templating to a JavaScript templating library. It’s a big ugly process, but a single-page app with a RESTful backend will be vastly easier to maintain than what I’ve got on my hands currently. But although just moving the templating & HTML generation over to the client will have benefits, if my JavaScript templates are as messy and unreadable as the JSP ones were, I can do better. Looking at the JavaScript templating libraries that are available, for the most part the templates themselves don’t look much different at all from the old server-side templating systems. For relatively simple views this isn’t really an issue, but when you start to put if/else tags in, especially when they start to get nested, or require you to stick conditions in there that are more complex than “is this attribute truthy/falsy”… it can get a little bit hard to follow, especially since you end up mixing HTML indentation and control structure indentation to the detriment of readability.

I realized that although the if/else logic in my existing JSP templates was fairly simple, I still had a much easier time wrapping my head around what’s happening and what combinations of HTML need to be generated in different situations by thinking of it in a slightly different way. I thought of the most generic possible template, with a series of transformations applied to it, each based on one condition, resulting in the final template to be filled with my model data & rendered. So I decided to implement such a system as an addon to Handlebars.js, the templating engine I decided on. Handlebars already encourages loading templates from the page like so:

So I decided to do a similar thing with transformation definitions:

What this is saying, is “if hasAuthor is true, change {{*author_info}} into {{}}{{*featured}}, if hasAuthor is false, change {{*author_info}} into Unknown Author,” and so on. The transformation rules will be applied in the order they appear in the script, so as you can see if hasAuthor is true, then it puts {{*popular}} into the working template, which can then be changed by a later rule in the same script or even by a totally different transformation script applied after this one. When you compile a template, any unused {{*}} tags are stripped out, so you don’t need a ! rule for items where you only want to conditionally include something or not, rather than choose between two different things to include. So, for example, using the template and transform above:

This results in:

There are downsides, of course – a template with the standard if/else tags can be compiled, whereas with this you’re basically defining many templates and you won’t know which one to apply until runtime. You could ameliorate this by precompiling each possible variation & writing some code to look up the one you want. This is just my first iteration on the idea, I’m sure there’s a lot that could be improved about it. But in any case it was fun to think about. I also put in code to use Handlebars in an OO-ish fashion, like so:

You can find the code on GitHub here.

Print Friendly