Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding visibility to expression in knockout

I have a series of images, and I only want one to be visible at a time, based on an observable property on my viewModel.

What I would like to have is something like this:

<img src="a.jpg" data-bind="visible: type == 'a'" />
<img src="b.jpg" data-bind="visible: type == 'b'" />
<img src="c.jpg" data-bind="visible: type == 'c'" />

...

Where 'type' is a simple ko.observable property on my viewModel. The above binding does not work when the value of 'type' changes. The workaround I have is to make a dependentObservable for each potential type like this:

viewModel.isA = ko.dependentObservable(function(){
    return this.type() == 'a';
}, viewModel);

That works, but it causes my code to grow pretty big. I feel like the expression binding should work, and I may have just gotten the syntax off by a little. Is there a clean way to do this?

like image 435
captncraig Avatar asked Oct 11 '11 22:10

captncraig


2 Answers

Sean's answer is correct about the syntax for type in your binding.

However, if you are concerned that you are creating too many dependentObservables and don't want the full expression in your binding, then you can use a simple function instead. KO bindings are internally executed inside of dependentObservables, so any observables that are accessed will create a dependency for that binding. This means that you can create a function like:

viewModel.isType = function(type) {
  return type === this.type();
};

Then you can use it like: (also the binding is called visible and not visibility)

<img src="a.jpg" data-bind="visible: isType('a')" />
<img src="b.jpg" data-bind="visible: isType('b')" />
<img src="c.jpg" data-bind="visible: isType('c')" />

Here is a sample: http://jsfiddle.net/rniemeyer/kbC2k/

like image 124
RP Niemeyer Avatar answered Nov 08 '22 02:11

RP Niemeyer


When accessing data in a non-trivial Knockout data-bind expression you need to call the observable as a function in order to get the underlying value:

<img src="a.jpg" data-bind="visible: type() == 'a'" />
<img src="b.jpg" data-bind="visible: type() == 'b'" />
<img src="c.jpg" data-bind="visible: type() == 'c'" />

However, if you are using a lot of non-trivial expressions in your data-bind attributes you probably better off creating a custom binding.

like image 35
Sean Vieira Avatar answered Nov 08 '22 02:11

Sean Vieira