Jade Templates Introspection
The Jade Template Engine for Node now have the ability to manipulate themselves based on the parse tree constructed from a nested block. This has extreme potential, in that developers can now alter jade templates dynamically, constructing their own syntactic sugar.
One of my favorite (but not only) use-cases for this functionality, would be that of a database record edit form. Typically your template may be littered with helper functions such as input(‘text’, user.name) or similar. With the ability for filters to now accept a block of tags, we can apply the Visitor pattern in order to convert tags to other tags, alter existing tags or manipulate Jade in almost any way without writing an entirely new compiler.
So how is something like an edit form typically handled? With rails / ERB it might look something like this, which although is “fine” it is generally in my opinion difficult to read, and clearly mixes code with the template.
Although Jade provides an arguably cleaner syntax, it does still essentially have the same issue of constantly mixing verbose logic within the template itself to do common things like display errors on a field as shown below.
With Jade’s new reflection capabilities we could vastly simplify these patterns by creating a :model filter and manipulating the parse tree. Below we lay out how we would prefer to handle model forms, we could take this even further and check model property types to attempt creation of the appropriate field types automagically, but for simplicity we will not.
Everything you see below is valid jade, however we utilize attributes to simulate argument passing, which is fantastic because we could easily transparently support input error handling without the use of our custom field tag.
The output we will achieve after our parse tree manipulation will be:
And here is our filter / Visitor implementation. Although the DOM-like node api is verbose, this extra layer adds endless flexibility to Jade, and while you are at it, why not generate the elements constructed below with Jade as well ;) using Jade’s new jade.parse(str) method.
Keep in mind that all of this is performed at the compilation level, typically which is only called once per template, so essentially no overhead over the lifetime of an application. That is it for now, make sure not to abuse this functionality :p.