When to Not Use Observable in KnockoutJS

javascriptI've been really busy lately and my list of things to blog on has been getting backed up. One thing that occurred to me while building my new JavaScript course was about how KnockoutJS and Observables actually work. Here's the deal.

KnockoutJS supports the idea of an observable object. This is similar to WPF/XAML concept of INotifyPropertyChanged interface. Most KnockoutJS dev's I've talked with use KnockoutJS's observable everywhere. But there are cases when you don't need it.

The biggest problem I see is that some people think that to get two-way binding you need observable.  For example, here is a JSFiddle with a typical (but simple) KnockoutJS example:

Here you see that the view model (e.g. src) is using an observable to create the properties. In the HTML, we have the name field bound twice...to the input box and to a div. This means than when we change the text in the first input box and that box loses focus, then the div changes as well. This is at the heart of what KnockoutJS's observable does. But in some cases, if you don't need the notification part of the functionality, a simple property is more efficient:

In this case, the code is identical but the viewmodel (e.g. src) is just using plain old JS members. While changing the text in the name input field doesn't make the div change (because the notification is missing), it does in fact handle two way binding. You can see this if you click the button (which pops up an alert showing the name in the view model.

For large apps that have a lot of bindings, this efficiency is helpful. Knowing when you can avoid using observable can help improve overall KnockoutJS performance.

What do you think?

 

Comments

Gravatar

Jason Thursday, September 27, 2012

Excellent guidance.

I often start with POJS, and then convert to observable as needed. This usually means that I need to go through and add parentheses in many different places later, but that's not a huge deal.

Note also that because they cache results, computed values dependent on non-observables will not recalculate if that value changes. That's one instance where you need to ensure that you are using observables to start with.

Gravatar

John west Thursday, September 27, 2012

You're right that this will help performance. It is no longer two way binding. It works the first time you apply the model, but after that, if you modify the value of the pojo, the input box will not be updated.

Gravatar

Knockout Nazi Thursday, September 27, 2012

First example:
alert(src.name);
should be:
alert(src.name());

Gravatar

Capaj Thursday, September 27, 2012

I think you may have forgot to put a "()" in the first JS fiddle example, because in the alert, there is something else printed out. Not using observable when you don't need them is probably clever thing to do. In the second case, where you don't use observables, I am really surprised that the two way binding really works. I'll have to look at that when I have time. That's absolute mystery for me.

Gravatar

Shawn Wildermuth Thursday, September 27, 2012

Thanks...fixed the JSFiddle.

Gravatar

Andrew Friday, September 28, 2012

Shawn, that's a great post on Knockout binding behavior.
It actually applies to SL\WPF too.

In other words, you do not need to make properties ko.observable(in WPF\SL would be to use INotifyPropertyChanged on the model) unless you update the property AFTER the model is bound to the UI.

The two-way data binding works between the name property and the div, WITHOUT the ko.observable.

In KnockoutJS, we have <input data-bind="value: name" />
In Silverlight\WPF, we have <Text="{Binding name, Mode=TwoWay}" />




Gravatar

Chris Marisic Friday, September 28, 2012

So does this mean you can basically boil down that if your entire usage of a property is <input data-bind=value:Foo

that there is really no need for Foo to ever be an observable because it's changes don't need to notify other fields?

Gravatar

Anthony Wieser Friday, September 28, 2012

My favorite trick was replacing a member from a JSON fetch with an observable of the same value in it's place. I do this only for properties that need updating...

function (data) { data.results.forEach(function (x) {
x.attending = new ko.observable(x.attending); });
...
}

Gravatar

Alexei Sunday, September 30, 2012

As John west has already pointed out the second example does not result in a full-fledged two way binding since none of the bound HTML elements are updated upon the src.name property update. In this direction it is just one time binding. Below is a quote from the Knockout documentation:
"...If this parameter is an observable value, the binding will update the element’s value whenever the value changes. If the parameter isn’t observable, it will only set the element’s value once and will not update it again later."

So there is nothing new in the provided example but the phrase "... it does in fact handle two way binding" is not accurate.

Gravatar

Shawn Wildermuth Sunday, September 30, 2012

Alexei,

I believe that it is two way, or one-time/two-way (the terms are confusing). When I refer to two-way, I specifically mean that you can fill a control and have the changes in the UI updated to the object. Notifying a change to the object back to the UI is notification AFAIAC. I still use Observables a lot, I just find I don't need them in every case to make KnockoutJS work.

Gravatar

Stephane Tuesday, October 02, 2012

I will say that to get two-way binding, you still need 'observable' but in many cases, you are right, we can use this 'OneTime/OneWayToSource binding mode', it is sufficient.

Gravatar

Sean Thursday, January 30, 2014

Good article on the topic. Do you think it would be fair to say, "If changing one element on the page should reflect in another element on the page, then use observable. Otherwise you can probably get away with a non-observable." ?


Leave a Comment

*
*
*