Question

I have this spinner.

When set it is ok, control shows the right value, no error message, but if I change it, every time I get this error message:

"TypeError: observable is not a function"

in this line:

observable($(element).spinner("value"));

This is a line in my customize binding, which goes like this:

ko.bindingHandlers.spinner = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    //initialize datepicker with some optional options
    var options = allBindingsAccessor().spinnerOptions || {};


    $(element).spinner(options);

    //handle the field changing
    ko.utils.registerEventHandler(element, "spinchange", function () {
        //var observable = valueAccessor();
        var observable = ko.utils.unwrapObservable(valueAccessor());
        observable($(element).spinner("value"));
    });

    //handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).spinner("destroy");
    });

  },
  update: function (element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor()),
        current = $(element).spinner("value");

    if (value !== current) {
        $(element).spinner("value", value);
    }
  }
};

If I swap the line that fails with the one that is commented out:

var observable = valueAccessor();

it works fine. Why does the first one fail?

Was it helpful?

Solution

In a custom binding the valueAccessor is a function which returns of the value of the binding, so what you have on the "right side" in the binding.

So in the case of data-bind="spinner: yourValue you will get the content of the yourValue property.

If your yourValue is ko.observable then in var observable = valueAccessor(); the observable will contain your actual observable function from yourValue what you can set it now to any value with:

var observable = valueAccessor();
observable($(element).spinner("value"));

So this is the correct usage in this case because you need to reference and use your observable function and not its value.

However if you use ko.utils.unwrapObservable(valueAccessor()); then its is automatically unwraps your observable so you will end with a value not a function. So this call is roughly equivalent to write valueAccessor()();

So if your view model looks like this:

vm = {
   yourValue: ko.observable(5);
}

When you write:

var observable = ko.utils.unwrapObservable(valueAccessor());
observable($(element).spinner("value"));

observable will contain the value 5 and not a function so you get the above mentioned exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top