Advanced techniques In this section, we are going to speak about some advanced techniques. We are not going to add them to our project because there is no need, but it's good that we know we can use these methods if our application requires it. Controlling descendant bindings If our custom binding has nested bindings, we can tell our binding whether Knockout should apply bindings or we should control how these bindings will be applied. We just need to return { controlsDescendantBindings: true } in the init method. ko.bindingHandlers.allowBindings = { init: function(elem, valueAccessor) { return { controlsDescendantBindings: true }; } }; www.it-ebooks.info Chapter 3 [ 69 ] This code is telling Knockout that the binding called allowBindings is going to handle all the descendant bindings: <div data-bind="allowBindings: true"> <!-- This will display 'New content' --> <div data-bind="text: 'New content'">Original content</div> </div> <div data-bind="allowBindings: false"> <!-- This will display 'Original content' --> <div data-bind="text: 'New content'">Original content</div> </div> If we want to extend the context with new properties, we can extend the bindingContext property with new values. Then we only need to use ko.applyBindingsToDescendants to update the view-model of its children. Of course we should tell the binding that it should control the descendant bindings. If we don't, they will be updated twice. ko.bindingHandlers.withProperties = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { var myVM = { parentValues: valueAccessor, myVar: 'myValue'}; var innerBindingContext = bindingContext.extend(myVM); ko.applyBindingsToDescendants(innerBindingContext, element); return { controlsDescendantBindings: true }; } }; Here we are not creating a child context. We are just extending the parent context. If we want to create child contexts to manage descendant nodes and have the ability to use the $parentContext magic variable to access our parent context, we need to create a new context using the createChildContext method. var childBindingContext = bindingContext.createChildContext( bindingContext.$rawData, null, //alias of descendant item ($data magic variable) function(context) { //manage your context variables ko.utils.extend(context, valueAccessor()); }); ko.applyBindingsToDescendants(childBindingContext, element); return { controlsDescendantBindings: true }; //Important to not bind twice www.it-ebooks.info Custom Bindings and Components [ 70 ] Now we can use the magic variables inside our child nodes: <div data-bind="withProperties: { displayMode: 'twoColumn' }"> The outer display mode is <span data-bind="text: displayMode"></span>. <div data-bind="withProperties: { displayMode: 'doubleWidth' }"> The inner display mode is <span data-bind="text: displayMode"></span>, but I haven't forgotten that the outer display mode is <span data-bind="text: $parentContext.displayMode"></span>. </div> </div> By modifying binding contexts and controlling descendant bindings, you have a powerful and advanced tool to create custom binding mechanisms of your own.