Enlive snippets for a table of data

By: on September 30, 2010

This is a walkthrough of using enlive templates in clojure to populate an html page with a table of data.

This is the reference html as supplied by a web designer, the web designer is a very grumpy man and is insisting that you mustn’t change a line of his html or it will break when viewed with Lynx or IE 4.

I would like to use this markup in an application but substitute my own data within the HTML. We could use hiccup to code up the layout in pure Clojure but this will make it difficult for any HTML developer to carry out any further development, this is unfortunate since most web developers know more about HTML than I do. We could use a templating solution like Freemarker or Velocity and is a good solution if you have a co-operative HTML developer. Our web developer is adamant that HTML and Javascript is all he is going to write and that the HTML is sacred. We could use XSLT if the HTML happens to be XML compliant, our web developer isn’t convinced about XML, he says that the browsers don’t demand it and he gets to type less characters into notepad if he can use <br >. But seriously, a lot of my projects have had HTML produced by other companies, in other countries and the process of pulling it apart, adding dynamic data driven behaviour and then getting to do it all again with updated HTML every couple of weeks as changes occur is a real chore. I want a solution where I don’t need to edit HTML and I think enlive gets very close.

Enlive is an html transformation library that uses CSS selectors to transform and alter existing HTML. In the same way that JQuery uses selectors to add animations or alter the DOM, enlive uses selectors and clojure code to transform and alter HTML without touching the HTML.

The fundamental operations in enlive are deftemplate and defsnippet. deftemplate defines a complete html template in which values can be substituted or altered. defsnippet is used to define fragments of HTML which can be used to construct complete HTML template. I’ll work through templating the HTML above to show how the complete page is built up from snippets.

This extract declares a variable that holds the location of the HTML file we are using as our template. The defsnippet declaration then defines a snippet based upon a the first th element in the first row of the table header that substitutes the value passed to the snippet into the content of the th element. The defsnippet form takes a name for the snippet, a base template, an expression that defines a CSS selector and a set of arguments, the body of the snippet contains a CSS selector matched with some code to execute. For this snippet we match the whole of the element with the [:th] expression and just substitute its content with the value passed to the snippet.
The REPL output shows the snippet being tested, internally enlive treats HTML as nested maps, if we change the base html, for example by adding a class and an id, this will be reflected in the snippet.

We can use this snippet to build up a larger snippet for the whole table header. Note how the whitespace in the template is being preserved in the output as the escaped tabs and newline characters.

Continuing this process of building snippets and combining them with standard clojure we end up with this:

This is a fair chunk of code but it does handle the special cases of odd and even rows and that the first table column uses a particular class without altering the HTML template. It could also be simplified by using some additional enlive functions and macros to remove similar code structures. Here is the output at the REPL for the whole table.

The code can then be used with other clojure libraries such as ring or compojure to produce a dynamic html table driven from data.



  1. Frank Shearar says:

    Your github links are missing a colon after “http”.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>