Client Side Templating with JsRender

Posted by: Sumit Maitra , on 10/22/2012, in Category HTML5 & JavaScript
Views: 71434
Abstract: This article explores the JavaScript library JsRender for creating HTML templates.

This article was co-authored by Sumit Maitra and Minal Agarwal

Developers familiar with server side technologies like WebForms on ASP.NET can easily relate to ‘controls’ like GridView and ListView. These ‘controls’ were very useful for rendering repeating data for example in a List for a single dimensional array and a grid for two-dimensional array of data. These ‘controls’ had a feature wherein at design time, we could specify how a single cell or row of data should look and behave, and at runtime, with real data, the server would render the entire grid as per the specified template. Essentially the design and behavior would be replicated, for each iteration of data.

However with the popularity of JavaScript and the general movement away from server side rendering to client side rendering, we have lost the benefit of server side templating and are reduced to writing string concatenation routines in JavaScript.

Essentially without templates we had to do a lot of inline JavaScript, looping over datasets.

dncmag This article is published from the July Edition of the DNC Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months.

The July edition featured hot topics like ASP.NET MVC4, SignalR, Knockout.js, jsRender, TDD, Visual Studio ALM, HTML5, SharePoint, Windows Azure and Metro Applications amongst others. Not to mention, a freewheeling interview with Ayende Rahien, the man behind RavenDB.

Download this Free Magazine Here

JsRender, a brief history

With the rise of JavaScript came some phenomenal JavaScript engines viz. jQuery, Dojo and others. Templating was a problem readily recognized and towards that end came jQuery-Template library. However development on jQuery-Template was paused after beta and eventually it was dropped from being considered as possible templating plugin due to fundamental direction-change on templating requirements set forth by the jQuery UI team. However, Boris Moore the chief contributor continued on a derivation of jQuery-Template and split up the implementation into JsRender (templating) and JsViews (View Model and Observables behavior). As of February 2012, JsRender is now approaching Beta, showing great promise of significant performance + feature when compared to other jQuery templating plugins like Handlebar, Strappend and Mustache.

Features

With the history out of the way, let’s jump straight into some basic usage. Let’s take an example of a User Identity object that we need to render. The Identity has the following structure

image

Now let us say we have a list of such Identity objects in JSON. The data would be as follows:

js-render

To render this data without templating, our approach would be to have an empty container in the markup and JavaScript text injection in a separate JavaScript file. Or embed the script inside a section in the markup itself

Markup (Approach 1)

markup-approach-1

JavaScript to Render

render-address

As we can see above, the script (that was supposed to have render logic only) now has a big set of markup as well. This kind of spaghetti development soon becomes unwieldy and large for a UI with even moderate complexity.

This is where templates come into play. In the next section, we see how to render the above with JsRender templates and understand the templating syntax.

Sample – A Contact List using JsRender

Note: This sample takes off from where Sumit Maitra’s Gravatar article on www.devcurry.com left. The original article takes user input for a contact sheet and looks up their Gravatar. We have modified the data being collected to highlight features of JsRender.

Before we get into the Gravatar part, let us simply render our sample data using JsRender. To do that, we update the markup as follows:

template-output-container

This div will contain the output that comes from after the data has iterated through the template below.

templated-markup

This is the syntax for specifying the JsRender template. Let us look at it in more details.

Understanding the Basic JsRender Templating Syntax

We can see in the markup above, we have some syntax that is not standard HTML. This is the special JsRender syntax. Let’s take it apart line by line

- Wrapping the template in Script: We see our template for showing a contact is wrapped in a Script area with it’s src set to the JsRender JavaScript and the type set to a special type of “text/x-jsrender”. This tells JsRender engine to treat this element specially.

- Template tokens {{ : }} - This is the fundamental JsRender token. It indicates to the library that it should try to ‘interpret’ the contents inside these tokens.

- Colon (:) = No Encoding - This retrieves the data-bound value from the object and shows the text as is (it will render HTML content in the text if any). If we don’t want to render HTML and spit out the raw html markup (if any), we can use the {{>}} syntax.

- Access inner objects by name: If we look at the Address object that has child elements, JsRender is accessing the child elements using the dot notation (which is common in languages as C# and Java). So binding to nested object graphs is simply a matter of traversing the graph using the dot notation. Apart from the dot notation, JsRender also supports named properties so we could use {{ : #data[‘name’]}} to get the name also where #data give us the current data context.

With the basics out of the way, let’s take a look at what happens to our client script that earlier had the spaghetti of code and JavaScript? It looks as follows now:

templated-script

As we can see above, all the spaghetti of markup and JavaScript is now gone. All we have is a couple of lines of code. Thus we have separated the script from the HTML markup. It works as follows:

  • First we grab the container object our template output. In our case, it’s an empty
    with the Id as contactListContainer (as seen above).
  • Next we pick the name of the template ‘script’ we saw earlier and call the render method on it. The render method is what invokes JsRender.
  • Finally render method is passed the data source against which the binding should happen (addList in our case).

Once this hookup is complete, our sample JsRender app is ready to go. It renders the two addresses in the Array.

Additional JsRender Tokens

Apart from the above basic tokens, JsRender supports more tokens for rich templating functionality.

- The {{for}} token – Looping though a sub-array of objects in the data source is handled using the {{for}} token. For example, if our original Identity source had the option of multiple addresses instead of one, then the Addresses accessor would give us an array of addresses and we would have to loop through all the available addresses. We could do the required templating as follows

for-token

As we can see above, we are looping through the Addresses available in our each of the Identity objects in our data source using the {{for [child collection] }} … {{/for}} tokens

#data actually is the current context. So in the above example, #data.Line1 and simply Line1 would mean the same. However if address was a collection of strings only, then we wouldn’t be able to say #data.something. In such cases only specifying #data would retrieve the string data in current context.

- The {{if}} {{else}} Tokens : As is obvious, these tokens help evaluate conditions and thus render content conditionally based on data being bound. We add the following to our template to check if the Gravatar property is set in the data. If it is set, we add an image element. If not set, we don’t do anything

jsrender-if-condition

As we will see here, this will show the Gravatar image of new contacts as we add them.

That sums up the core tokens in JsRender. We will now complete our Contact List Application using JsRender templates instead of the inline markup + JavaScript we had earlier.

Completing the Contact List Application

- We update the ‘New Contact’ popup for the additional fields for the Address.

add-data-one

- Next we update the JavaScript to push the newly added data into our data source by calling the contactAdd(data) method.

contact-add

  • We first calculate the GravatarUrl using the calculateGravatar call.
  • We assign the Gravatar URL to the Gravatar property
  • We add the data in our data source object ‘addList’
  • Finally we call renderAddress() as defined above to re-render the UI with the new Data. The newly added data comes up as follows

new-data

With that, we have covered the most often used JsRender tokens and their usage. Our sample application is now complete. To round off with, we will look at a technique where JsRender templates can be compiled and kept for future use.

Compiling and Reusing Templates

JsRender templates can be compiled and kept away as strings and then invoked for rendering on demand. This gives a performance edge and also allows better reuse and separation of the template and the html markup.

The syntax for compilation is as follows

var templateString = ‘

{{:myVariable}}
’;
var compiledTemplate = $.templates(templateString); //this compiles the template
$(‘#templateContainer’).html(compiledTemplate.render(data));

Another way of compiling a template is to used named-templates

// templateLayout is the named template
$.templates(‘templateLayout’, ‘

{{:myVariable}}
’);
// templateLayout can be rendered as follows
$.render.templateLayout(data);

We should use compiled templates wherever possible primarily because of performance gains as well as the fact that it enables better separation of concerns. With that we conclude our introduction to JsRender and its Templating functionality.

Building data intensive UIs just got a whole lot easier!

Download the entire source code on GitHub (click on ZIP for a .zip file)

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Brendan on Thursday, October 25, 2012 6:44 AM
After I call render on my jsRender template it seems to disappear from the DOM. Any clues?
Comment posted by cc liu on Friday, October 26, 2012 12:31 AM
Great article, thanks a lot!
Comment posted by Sumit on Saturday, October 27, 2012 1:52 PM
Brendan,
The only reason I can think off is there is an exception at the time of binding. Can you share your code/sample? I can give it a try... sumitkm at gmail
Comment posted by Brad oyler on Sunday, November 25, 2012 9:37 AM
Curious as to why you are using JsRender over any of the other template frameworks like handlebars http://handlebarsjs.com/ . This approach is def really handy when using Web API
Cheers!
Comment posted by fdgdgfd on Monday, April 22, 2013 2:55 AM
l not be displayed)
Comment posted by Rajeev on Saturday, June 8, 2013 11:27 PM
refer this video http://www.youtube.com/watch?v=UGh5m7RO1FM