Rizqi Ahmad from Germany has introduced a nice solution for client-side template based on JQuery. The Chain.js allows you to use any piece of HTML (or embedded HTML string) as template to display data dynamically.
In introductory post, he went through some common approach like server-side data binding, injecting preformatted HTML (into well-known DOM property innerHTML) and directly manipulating DOM, then explained why Chain.js is better way:
- Easy and compact (as it uses JQuery for manipulating DOM)
- Preserve event(s) on updates
- Allow dynamically add/remove data
To use the engine, you’ll need to download JQuery (better the latest version) and Chain.js then add script tags to load them.
<script src="path/to/jquery.js" language="javascript"> </script>
<script src="path/to/chain.js" language="javascript"> </script>
Practical Example on Chain.js

Now, we’ll create a practical example that allows user select a programming language and display recommended reading books accordantly. This is almost similar to another example I created for PURE library.
First, build a template table to display book list:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <table class="books">
<thead>
<tr>
<th>Title</th>
<th>Publisher</th>
<th>Price</th>
</tr>
</thead>
<tbody id="book_table_body">
<tr class="item">
<td class="title"> </td>
<td class="publisher"> </td>
<td class="price"> </td>
</tr>
</tbody>
</table> |
Second, get data (books) from server based on selected language selected via Ajax using JQuery function $.getJSON().
1
2
3
4
5
| $.getJSON('json.php', 'lang=' + $('#langList').val(),
function(books){
........
}
); |
We’ll have a list of books in JSON format that looks like:
[{title: "Sams Teach Yourself Java 6 in 21 Days", publisher: "Sams", price: 29.69},
{title: "Java In A Nutshell", publisher: "O'Reilly", price: 29.67},
{title: "Effective Java", publisher: "Sun", price: 28.79}]
Then just tell Chain to parse the books and add them to the table body:
$('#book_table_body').items(books).chain();
All JavaScript codes to get it work are as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
| function render(){
$.getJSON('json.php', 'lang=' + $('#langList').val(), function(books){
$('#book_table_body')
.items('destroy') /* clear previous items */
.items(books) /* parse items */
.chain(); /* chain them */
});
}
$(document).ready(function(){
$('#langList').change(render); // handle change event of drop-down list
setTimeout(render, 100); // call render function on load
}); |
See this example online: Example 1. Select each language to see the book list below changed.
Add/Remove & Sort Items

Chain.js supports adding, removing and sorting items with minimal efforts. To visualize the functionality, we’ll create some INPUT fields to add new data to the book table.
1
2
3
4
5
6
| <div class="add-data">
Title: <input id="input_title" type="text" width="10" />
Publisher: <input id="input_publisher" type="text" width="10" />
Price: <input id="input_price" type="text" width="10" />
<input type="button" value="Add" onclick="addData()" />
</div> |
Then, define addData() function that responses to “onclick” event of Add botton :
1
2
3
4
5
6
7
| function addData(){
var data = [{title: $('#input_title').val(),
publisher: $('#input_publisher').val(),
price: $('#input_price').val()}];
$('#book_table_body').items('add', data);
} |
To support removing a row by double clicking on it, we’ll bind the event on chain method:
1
2
3
4
5
6
7
8
| $('#book_table_body')
.items('destroy') /* clear previous items */
.items(books) /* parse items */
.chain(function(){ /* bind event */
this.dblclick(function(){
$(this).item('remove'); // remove item
});
}); |
The last functionality we wish at the moment is to sort items. First, we have to create some links on table header:
1
2
3
4
5
6
7
8
9
10
| <table class="books">
<thead>
<tr>
<th><a href="javascript:void(0)" onclick="sortBy('title')">Title</a></th>
<th><a href="javascript:void(0)" onclick="sortBy('publisher')">Publisher</a></th>
<th><a href="javascript:void(0)" onclick="sortBy('price')">Price</a></th>
</tr>
</thead>
…
</table> |
And define sortBy() function to handle sorting items by column, not complicated as you may think:
1
2
3
| function sortBy(col){
$('#book_table_body').items('sort', col, {toggle:true});
} |
That’s all. Please see online example: Example 2 and feel free to add items, to remove one by clicking on the row and sort them (ascendant or descendant).
Advanced Custom Data Binding

The last example is to explore a bit advanced functionality which I find very useful in practice: custom data binding. As you can see in the above examples, data binding are made by default: Chain.js matches data field with element class name and render text into it. In practice, it’s very often that we want to format or bind data to sub-elements instead.
For example, now we want to:
- Format “Price” to fixed 2 decimal, add a dollar sign before number and make it align at right.
- Add another column called “Order” that link to order page (say http://amazon.com/…)
The template table must be modified to add a new column (Order) that contains a link by default:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <table class="books">
<thead>
<tr>
<th>Title</th>
<th>Publisher</th>
<th>Price</th>
<th>Order</th>
</tr>
</thead>
<tbody id="book_table_body">
<tr class="item">
<td class="title"></td>
<td class="publisher"></td>
<td class="price3"></td>
<td class="order">
<a class="order-link" href="#"></a>
</td>
</tr>
</tbody>
</table> |
On chain method, we’ll define a directive to tell Chain how to bind data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| $('#book_table_body')
.items('destroy') /* clear previous items */
.items(books) /* parse items */
.chain(
/* Custom data binding */
{
'.price3': {
style: 'text-align: right',
content: function(data, el){
return '$' + data.price.toFixed(2);
}
},
'.order .order-link': {
style: 'color: red;',
href: '{orderLink}',
target: '_blank',
content: 'Order Now!'
}
}
); |
Only problem I found is the custom data binding does not override default one so that I have to rename class of price row to “price3” or Chain won’t parse the directive (but simply use “raw” price number as Example 1). Hope Rizqi Ahmad will fix that in the next version?
Online example is here.
Conclusion
Chain is very nice and comprehensive solution I can find among many others, thanks to compact syntax and simplified DOM manipulate method by JQuery — Just write less and do more with HTML template! Please download all source codes of above examples at the following link.
Update: Revised examples based on Chain.js v0.2 can be found here.
Download source codes