Knockout.js pro tips – working with templates

Β· 839 words Β· 4 minutes to read

Just like last time, when we discussed observable arrays, I wanted to share a few (hopefully) useful tips about working with templates in Knockout. This is not going to be a comprehensive look into templating with knockout - there are plenty of resources that cover that - but rather a collection of smaller pieces of advice that could make you life easier.

Again, familiarity with Knockout is assumed.

Easy, reusable templating in Knockout.js πŸ”—

Templating can be a pain if you want to reuse the same template over multiple pages. You are not going to copy paste your templae in every page, are you? You could be using the excellent Knockout.js External Template Engine instead.

In short, it allows you to define the templates in external files and load them dynamically on runtime. It actually plugs itself very well into KO, as it overrides the existing template engine, so you can use all the same familiar bindings.

A quick peek at the code. Let’s say you have a team template that you wanna reuse over and over. Declare it in a separate file.


  * ### <span data-bind="text: location"></span>  
    <span data-bind="text: name"></span>  
    

Now in your HTML, reference the engine

  

You need to specify the relative path to your templates in your JS code.

infuser.defaults.templateUrl = "templates";  

And you can start using the template, calling them using KO’s familiar “name” property of the template binding.

<ul data-bind="template: { name: 'team', foreach: filteredTeams }">
</ul>

By default the name of the template actually corresponds to the name of your template file. There is a ton of other congiuration options, such as name suffix/prefix, or caching options, so make sure to check them out! But most importantly, you can now call the same template on different pages.

You can render templates directly from your custom bindings πŸ”—

If you find the need to do so, you can manually render templates from your JS code. One such example could be rendering templates from your custom bindings (which might do some sopohisticated, tailored processing).

Consider a simple example:

function homeViewModel() {  
var self = this;  
self.dummy = {  
dummyText: ko.observable("text")  
}  
}  

Now, imagine you have some custom binding - you can easily render templates from it:

ko.bindingHandlers.myBinding = {  
update: function(element, valueAccessor, allBindingsAccessor) {  
var accessor = valueAccessor();  
//do cool stuff  
ko.renderTemplate("myTemplate", accessor, {}, element, 'replaceNode');  
}  
};  

The renderTemplate method takes in templateName, bindingContext, rendering engine options, DOM element to use and template rendering mode as arguments.

And you would setup the HTML accordingly:


<div data-bind="myBinding: dummy">
</div>

  

Of course this is a very trivial sample, but I hope it illustrates the gist of it - leveraging on ko.renderTemplate, and calling it manually whenever needed.

Use inline templating whenever possible πŸ”—

Inline templating - and using foreach binding, performs around 1/3 faster than applying template from a separate DOM element, the so-called named template binding.

Michael Best has put together a really nice performance shootout between the two approaches.

So whenever you do not plan to reuse the template use the inline foreach binding instead of separate template element.


<ul data-bind="foreach: teams">
  <li>
    <h3>
      <span data-bind="text: location"></span><br /> <span data-bind="text: name"></span><br />
    </h3>
  </li>
</ul>

You can render a template within a template πŸ”—

This might seem like a trivial thing but many people don’t know about it. You can actually reference another template in a template and build up your HTML output like that.

This way you might have smaller reusable snippets of HTML to use on different pages and inside of different templates.

So it’s perfectly fine to do something like this:

<div data-bind="template: { name: 'teamIndex', foreach: teams }">
</div>

You could also pass the data or foreach property to the child template to change its context. Again, a simple example:

<div data-bind="template: { name: 'league', foreach: leagues }">
</div>

As you see, you can structure your data and reuse your templates quite easily that way.

Avoid combining other bindings with template binding πŸ”—

This is a great insight provided by one and only RP Niemeyer on his blog.

Basically, due to the nature of how binidngs are processed, you should avoid combining other bindings with template binding, especially under data-heavy scenarios. Knockout uses one computed observable to track all binidngs of an element, so change to one dependency triggers update events for all of the element’s bindings. I really recommend reading that article by Ryan, it’s a terrific insight into the inner wokrings of Knockout.

Example. Instead of combining them on one DOM element:

<ul data-bind="visible: showingTeams, myCustomBinding: userUIPreferences, template: { name: 'team', data: teams}">
</ul>

Split them:

<div class="wrapper" data-bind="visible: showingTeams, myCustomBinding: userUIPreferences">
  <ul data-bind="template: { name: 'team', data: teams}">
  </ul>
</div>

Summary πŸ”—

Templating is a large and important part of Knockout.js. As everything in JavaScript it can be extremly powerful and flexible, but if not used properly can lead to nasty consequences.

Hopefully a couple of these tips will help manouver through the exciting worl of Knockout!

Ps. This article has also been translated to Serbo-Croatian language by Vera Djuraskovic from Webhostinggeeks.com.

About


Hi! I'm Filip W., a software architect from ZΓΌrich πŸ‡¨πŸ‡­. I like Toronto Maple Leafs πŸ‡¨πŸ‡¦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁒󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP