Saturday, January 17, 2009

Javascript Templating

Writing HTML with Javascript has always been a necessary evil, and for me a painful thing to look at in code. Usually we have to do this when we've got some set of data in a collection on the client, and we need to loop through the collection and build HTML.

Back in the day, before I was privy to Javascript templating, I'd do this:


var myArray = ['John', 'Steve', 'Bill'];
var myHTML = '';
for(i=0;i<myArray.length;i++) {
myHTML += '<div>Hello, my name is ' + myArray[i] + '.</div>';
}
var container = document.getElementById('myContainer');
container.innerHTML = myHTML;

There's a few things wrong with this. It's everything bad about the close intermingling of two different languages, or having one language write the other. It's also extremely inefficient. The concatenation of the string results in 3 additional strings allocated during each iteration. And finally, what if my data structure gets more complicated (which in this case, there's no doubt it will), and the array becomes multi-dimensional, then this code gets even more gnarly.

Today, with the arrival of Javascript frameworks like Prototype, jQuery and Dojo, doing this work becomes not only trivial, but much better performing. I'm going to use Prototype for my examples here, but you'll find the other frameworks only differ slightly in semantics.

//use a more descriptive structure
var myData = [{name: 'John'}, {name: 'Steve'}, {name: 'Bill'}];

//Template is a Prototype class
var template = new Template('<div>Hello, my name is #{name}.</div>');

//each is a handy Prototype array extension
myData.each(function(item) {
//the $('foo') syntax is Prototype shorthand for getElementById.
$('myContainer').insert(template.evaluate(item));
});

Definitely a much cleaner approach here. With the old way of doing things, as the complexity of what you have to display grows, the complexity of the code is exponential. However, with the template approach, complexity is closer to linear.

1 comments:

Ben said...

That's perty.