In the Display JSON Data Using the JsRender Template Engine article, we learned about the JsRender template library. The successor to the jQuery Templates plugin, JsRender’s declarative syntax provides separation of presentation and behavior, and includes many notable features, such as the ease of creating custom tags, and increased performance. Of course, once the rubber hits the road, you quickly discover the practical limits of declarative syntax. There has to be some programming logic to handle special circumstances, for instance, calculated fields. In today’s tutorial, we’ll take advantage of two JsRender features for processing data values, namely converter and helper functions.
Converter Functions
JsRender converters offer a convenient way of processing or formatting a data value, or the result of expression evaluation.
JsRender provides a few built-in converters to HTML-encode, attribute-encode, and URL-encode:
{{html:movie.description}} - This data is HTML encoded
{{>movie.description}} - (Alternative syntax)
{{attr:availability}} - For use in HTML attributes
{{url:~getTheFilePath()}} - This expression will be URL-encoded
Here is our data set from the Display JSON Data Using the JsRender Template Engine article with a new dob field. We’ll be using it for some our examples today:
var names = [
{
"name": "Robert",
"nickname": ["Blackjacques", "Rob"],
"showNickname": true,
"dob": "1969-01-14"
},
{
"name": "Jeanie",
"nickname": "",
"showNickname": false,
"dob": "1968-06-12"
}
];
You have the option of registering your helpers globally, so that they may be used in any template, or as private to a parent template. We’ll start by registering a global function to convert a data value to uppercase. Here’s the syntax for that:
$.views.converters(name, converterFunction)
Plugging in the name and function code for our toUpper() function results in the following code:
$.views.converters("toUpper", function(val) {
return val.toUpperCase();
});
Back in our template, all we have to do is prepend our function to the field that we cant to convert:
<em>Name:</em> {{toUpper:name}}
And voila, the names are now in uppercase!
Name: ROBERT (Goes by Blackjacques,Rob)
Name: JEANIE
Converters are also perfectly suited for transforming data such as currency, dates, and times into different formats. Which brings us to our new dob field. It’s in ISO 8601 date format, which is ideal for representing dates in such a way as to avoid misinterpretation when data is transferred between countries with different conventions for writing numeric dates and times. That being said, we might want to format the dates to be more meaningful to us, such as a long date.
The following converter uses the toLocaleDateString() function to do the job. It accepts local information as well as an options object that provides information on the appearance of each datepart:
$.views.converters("formatDate", function(val) {
return (new Date(val)).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric'
});
});
Here is the updated output:
Name: ROBERT (Goes by Blackjacques,Rob)
Date of Birth: January 13, 1969
Name: JEANIE
Date of Birth: June 11, 1968
You can also register multiple converters as an Object literal (hash) of keys (name of helper) and values (function, object, or value):
$.views.converters({
toUpper: function(val) {
return val.toUpperCase();
},
formatDate: function(val) {
return (new Date(val)).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric'
});
}
});
You may view the full demo on CodePen.
Helper Functions
It helps to think of helper functions as those that do not massage existing fields, but create new data that does not exist within the data set as such. For instance, here’s a helper called “calcAge” that computes the person’s named based on their date of birth (dob). It utilizes the helpers constructor that accepts an object of helper functions as well as the template instance to register the functions to. Doing so makes them private to that particular template.
var template = $.templates("#theTmpl");
$.views.helpers({
calcAge: function(dob) {
if (typeof(dob) == 'string') dob = new Date(dob);
var dateToCalculate = new Date();
var calculateYear = dateToCalculate.getFullYear();
var calculateMonth = dateToCalculate.getMonth();
var calculateDay = dateToCalculate.getDate();
var birthYear = dob.getFullYear();
var birthMonth = dob.getMonth();
var birthDay = dob.getDate();
var age = calculateYear - birthYear;
var ageMonth = calculateMonth - birthMonth;
var ageDay = calculateDay - birthDay;
if ( ageMonth < 0
|| (ageMonth == 0 && ageDay < 0)) {
age = parseInt(age) - 1;
}
return age;
}
}, template);
The syntax for invoking a helper function from within your templates is a little different than converters. Helpers typically start with a colon (to include the result as is) or a greater than sign (>) (to html-encode the result), proceeded by the tilde character (~) and the function, complete with parentheses and function arguments. The parentheses may be omitted if the function does not accept any arguments:
<em>Date of Birth:</em> {{formatDate:dob}} (<em>Age:</em> {{:~calcAge(dob)}})
Name: ROBERT (Goes by Blackjacques,Rob)
Date of Birth: January 13, 1969 (Age: 48)
Name: JEANIE
Date of Birth: June 11, 1968 (Age: 49)
Here’s the helpers demo.
Conclusion
The ability to invoke built-in or custom functions, along with a pure string-based approach to templating, both make JsRender a very flexible and efficient template library.