Knockout JS: How to change the data context for an HTML node

As I explored Knockout, I encountered a scenario where I needed to change the data context for a node and it's descendent nodes. And to stop the bindings from one of this node's ancestors from propagating.

Knockout provides a couple of ways to do this: -

  • Use the "with" binding: which allows you to provide an alternate binding context. This however has the limitation that the value provided to the with binding needs to be obtained in some manner from the parent element's data context.
  • Alternatively, you could create a custom binding handler and in the ini method return an object with the field controlsDescendentBindings = true; click here for more details. Well, if you debug through the "with" binding, you will realize that it also uses the controlsDescendentBindings attribute I mentioned earlier.

Below is some sample code which shows how you can achieve this. For convenience, I have used JQuery to manipulate the DOM. This however is not a necessity.

** * HTML Template * **

<div id="test">
    <div data-bind="text: title"></div>
    <div class="inner-node"></div>
</div>

** * JavaScript * **

var element = $("#test");

ko.applyBindings({
    title: "Hello World!"
}, element[0]);

ko.bindingHandlers.custom = {
    init: function () {
        return { controlsDescendentBindings: true };
    },
    update: function () {

    }
}

var innerElement = element.find(".inner-node");

innerElement
    .html("<div data-bind='text: innerTitle'></div>")
    .attr("data-bind", "custom: $root");

ko.applyBindings({ innerTitle: "Inner Title" }, innerElement[0]);

Happy Coding!