Question

I am trying to encapsulate the creation of an observable inside a custom binding, much like isValid of knockoutjs-validation, but without extending the binding because this property in the future will be the result of another binding that records a complicated sequence of events on the input and it feels like i shouldn't do more than using a custom binding for this.

The following code shows my custom binding responsible for the creation of the observable.

ko.bindingHandlers.myBinding = {
  init: function (
  element, valueAccessor, allBindingsAccessor,
  viewModel, bindingContext) {
    console.log("init myBinding");

    var observable = valueAccessor();
    observable.IsRed = ko.observable(true);
    console.log("isred created");

    ko.applyBindingsToNode(element, {
      value: observable,
      mySubBinding: observable.IsRed
    }, viewModel);
    console.log("finish myBinding");
  },
  update: function (
  element, valueAccessor, allBindingsAccessor,
  viewModel, bindingContext) {
    console.log("update myBinding");
  }
};

The problem i am having is that the observable seems to be created after part of the applyBindings command is executed and only posterior bindings on the View can see the right value of the observable.

I wrote a jsfiddle to show the behavior. In it, IsRed is the observable in question.

http://jsfiddle.net/ricardomp/c2HnJ/15/

The expected result would be the input with red background and the span tags before and after with the same value.

What can i do to accomplish that result? The result binding should not be dependent of any outside observable or property, right? Would you propose an alternative implementation?

Thanks in advance.

UPDATE:

I think its worth mentioning that myBinding is a binding that encapsulates multiple bindings. So, like IsRed, i will have 3 or 4 more bindings being assigned to similar observables.

FINAL UPDATE:

After RP's answer i wrote the following code to accomplish the initialization of the observables:

ko.observable.fn.colorStatus = function () {
    this.isRed = ko.observable();
    this.isGreen = ko.observable();
    this.isBlue = ko.observable();

    this.ResetStatus = (function () {
        this.isRed (undefined);
        this.isGreen (undefined);
        this.isBlue (undefined);
    }).bind(this);
    return this;
};

After that i only needed to call colorStatus on my observable when it is being initialized.

self.value = ko.observable().colorStatus();

And that's all.

Was it helpful?

Solution

The problem is that when the binding string is evaluated for the first two bindings in your jsFiddle example $root.Test.IsRed is undefined.

So, it is the equivalent of binding text: undefined. It is not an observable yet, so it there are no dependencies created and the binding does not update.

You would need to ensure that IsRed is created before anything uses it in the binding string . You could do this in your view model itself using an extension (either extenders or extending the base types). Otherwise, you could add a binding that adds it on a previous element.

The important part is that IsRed exists before a binding string is parsed that includes it.

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