Dragos
Dragos

Reputation: 776

Knockout unwrap observable does not work as expected

I have made an icon custom binding that works fine if I do something like this

<div data-bind="icon: 'icon-name'"></div>

I want the icon to be variable so in my view model I have:

var element = {
  icon: ko.computed(function() {
    return 'icon-' + iconType();
  }
}

In my html I have:

<div data-bind="icon: ko.utils.unwrapObservable(icon)"></div>

But this is not working. Note that if I insert another div before like this:

<div data-bind="text: ko.utils.unwrapObservable(icon)"></div>

I get a div with exactly the name of the icon that I wanted, lets say 'icon-1'.
So my guess is that unwrapObservable does not give me the text in the format I need.

Any ideas how to fix this?

The icon binding:

ko.bindingHandlers.icon = {
        init: function(element, valueAccessor) {
            var icon = ko.unwrap(valueAccessor());
            $(element).html(icons[icon]);
         }
}

Upvotes: 0

Views: 1206

Answers (1)

James Thorpe
James Thorpe

Reputation: 32202

Instead of init, you need to handle update, for when the value changes, which is what's happening with the computed:

ko.bindingHandlers.icon = {
    update: function(element, valueAccessor) {
        var icon = ko.unwrap(valueAccessor());
        $(element).html(icons[icon]);
    }
}

You should then be able to bind as normal, without needing to upwrap the value within the binding:

<div data-bind="icon: icon"></div>

With regards to init, the documentation says:

Knockout will call your init function once for each DOM element that you use the binding on. There are two main uses for init:

  1. To set any initial state for the DOM element
  2. To register any event handlers so that, for example, when the user clicks on or modifies the DOM element, you can change the state of the associated observable

IE it's not necessary here, you can do everything you need through update.

Upvotes: 2

Related Questions