Knockout JS does an excellent job in binding the interface with a View Model. Sometimes you’ll need some data manipulation before a value can be shown to the users. How would you go about?

A few options come to mind:

  • Extend the model with a computed property. Technically it is easy to extend your model, but is it the right thing to do? You are adding a new feature to the model… that might not be the right place to solve your problem. Let’s say we want to pretty print a dollar value, is that something you want to add to your model? Or should it be in a different layer?
  • Use a global function to the window. We could add window.printDollar(x){ return ‘$’ + (Math.round(x * 100) / 100); } and use it data-bind=”text: window.printDollar(price())” . This is a good solution for general tasks that are frequently used. But what if you need do something that is only needed in the current view?

Using more complex operations might result in the JavaScript exception: “Uncaught SyntaxError: Unable to parse bindings“.

Printing the position

Let’s say we need to list the position of an object in an observable array, with the following rules:

  • First position is 1 ($index + 1).
  • If position is lower than 10, prefix it with a zero.
  • Print a ‘.’ after each position.

First try: wrong way

When I tried to implement this, I used the following – but it did not work:

<span data-bind="text: { 
	var x = $index; 
	x += 1; 
	if(x < 10) x = '0' + x; 
	return x + '.'; 
} "></span>

KnockoutJS doesn’t know how to parse this and you’ll end up with an error.

Anonymous function to the rescue

The trick is to wrap it into an anonymous function and calling it with the index as a parameter. Because of the nature of this function, we’ll need to evaluate the observables that are passed (use () to get the value).

<span data-bind="text: 
	(function(i) { 
		i += 1; 
		if(i < 10) i = '0' + i; 
		return i + '.'; 
	})($index());
">
</span>

This technique is frequently used in JavaScript to achieve information hiding.