Rss feed

Simple JavaScript Templating

While working on a little side project of mine, I came across the need for a really simple method of performing HTML templating within JavaScript. Since JQuerys method had been deprecated, and seeing as I had no real requirement for any fancy functionality, I decided to quickly throw together my own implementation, which can be grabbed below.

 /**
 * TPL provides an ultra light weight, super simple method for quickly doing HTML templating in javascript.
 * @author Carl Saggs
 * @version 0.2
 * @source https://github.com/thybag/base.js
 */
 (function(){

	/**
	 * template
	 * Template a HTML string by replacing {attributes} with the corisponding value in a js Object.
	 * @param String (Raw HTML or ID of template node)
	 * @param JS Object
	 * @return NodeList|Node
	 */
	this.template = function(tpl, data){
		//Find out if ID was provided by attempting to find template node by ID  
		var el = document.getElementById(tpl);
		// If result is null, assume was passwed raw HTML template
		if(el !== null) tpl = el.innerHTML;
		//transform result in to DOM node(s)
		var tmp = document.createElement("div");
		tmp.innerHTML = replaceAttr(tpl,data);
		var results = tmp.children;
		//if only one node, return as individual result
		if(tmp.children.length===1)results = tmp.children[0];
		return results;
	}

	/**
	 * replaceAttr
	 * Replace all {attribute} with the corisponding value in a js Object.
	 * @param String (raw HTML)
	 * @return String (raw HTML)
	 * @scope private
	 */
	var replaceAttr = function(tpl, data, prefix){
		//Foreach data value
		for(var i in data){
			//Used for higher depth items
			var accessor = i;
			if(typeof prefix !== 'undefined') i = prefix+'.'+i
			//If object, recusivly call self, else template value.
			if(typeof data[i] === 'object'){
				tpl = this.replaceAttr(tpl, data[i], i);
			}else{
				tpl = tpl.replace(new RegExp('{'+i+'}','g'), data[accessor]);
			}
		}
		//return templated HTML
		return tpl;
	}

	//Add tpl to global scope
	window.tpl = this;
}).call({});

Essentially the code just provides a simple way of passing in some arbitrary HTML markup, then swapping out any contained {bla} tags with the values stored in the associated JavaScript object.
Say for example we had a array of people objects and we wanted to apply a simple template to them, before appending them in to our document. To do this you could use code similar to the following:

var test = [
	{"name":"Dave","age":22},
	{"name":"James","age":42},
	{"name":"Tim","age":27}
];
test.forEach(function(personObj){
	var el = tpl.template("<div class='person'><strong>{name}</strong><span class='right'>{age}</span></div>",personObj);
	document.body.appendChild(el);
});

Alternately if you had some more complex markup, or just wanted to separate the templates from the general script a little more, you can specify your template HTML in script tags (or any other elements) and reference them by id. For the example above you would just have something like this within your html document

<script id='myTemplate' type='text'>
	<div class='person'>
		<strong>{name}</strong>
		<span class='right'>{age}</span>
	</div>
</script>

Which could then be utilised in the following manner.

var el = tpl.template("myTemplate", personObj);

The script will also happily support passing in multidimensional objects which can be used in the templates as obj.attr.anotherattr etc.

As with most code I write, the source is on github and may be updated periodically with bug fixes and new features. Currently my templating method is incredibly basic and has almost no features compared to pretty much all others out there. That said, it does what I need it to, so its not all bad :)

Thanks for reading,
Carl


Leave a Reply