From a32bd19369af81f0b0b2aaf4486188c8670eb1c5 Mon Sep 17 00:00:00 2001 From: Michael Best Date: Sat, 15 Apr 2017 02:13:20 -0700 Subject: [PATCH] Add third parameter to ko.applyBindings for modifying the root context --- spec/bindingAttributeBehaviors.js | 21 ++++++++++++++++++--- src/binding/bindingAttributeSyntax.js | 8 ++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/spec/bindingAttributeBehaviors.js b/spec/bindingAttributeBehaviors.js index 5393c0874..edf441584 100644 --- a/spec/bindingAttributeBehaviors.js +++ b/spec/bindingAttributeBehaviors.js @@ -29,7 +29,7 @@ describe('Binding attribute syntax', function() { didInit = true; } }; - testNode.innerHTML = "
"; + testNode.innerHTML = "
"; ko.applyBindings(suppliedViewModel); expect(didInit).toEqual(true); }); @@ -44,10 +44,10 @@ describe('Binding attribute syntax', function() { didInit = true; } }; - testNode.innerHTML = "
"; + testNode.innerHTML = "
"; var shouldNotMatchNode = document.createElement("DIV"); - shouldNotMatchNode.innerHTML = "
"; + shouldNotMatchNode.innerHTML = "
"; document.body.appendChild(shouldNotMatchNode); this.after(function () { document.body.removeChild(shouldNotMatchNode); }); @@ -55,6 +55,21 @@ describe('Binding attribute syntax', function() { expect(didInit).toEqual(true); }); + it('applyBindings should accept three parameters and use the third parameter as a callback for modifying the root context', function() { + var didInit = false; + ko.bindingHandlers.test = { + init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { + expect(bindingContext.extraValue).toEqual("extra"); + didInit = true; + } + }; + testNode.innerHTML = "
"; + ko.applyBindings(null, testNode, function(context) { + context.extraValue = "extra"; + }); + expect(didInit).toEqual(true); + }); + it('Should tolerate empty or only white-space binding strings', function() { testNode.innerHTML = "
"; ko.applyBindings(null, testNode); // No exception means success diff --git a/src/binding/bindingAttributeSyntax.js b/src/binding/bindingAttributeSyntax.js index da5b0508f..94445a88a 100755 --- a/src/binding/bindingAttributeSyntax.js +++ b/src/binding/bindingAttributeSyntax.js @@ -399,10 +399,10 @@ return bindingInfo && bindingInfo.context; } - function getBindingContext(viewModelOrBindingContext) { + function getBindingContext(viewModelOrBindingContext, extendContextCallback) { return viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext) ? viewModelOrBindingContext - : new ko.bindingContext(viewModelOrBindingContext); + : new ko.bindingContext(viewModelOrBindingContext, undefined, undefined, extendContextCallback); } ko.applyBindingAccessorsToNode = function (node, bindings, viewModelOrBindingContext) { @@ -421,7 +421,7 @@ applyBindingsToDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode, true); }; - ko.applyBindings = function (viewModelOrBindingContext, rootNode) { + ko.applyBindings = function (viewModelOrBindingContext, rootNode, extendContextCallback) { // If jQuery is loaded after Knockout, we won't initially have access to it. So save it here. if (!jQueryInstance && window['jQuery']) { jQueryInstance = window['jQuery']; @@ -437,7 +437,7 @@ throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"); } - applyBindingsToNodeAndDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode, true); + applyBindingsToNodeAndDescendantsInternal(getBindingContext(viewModelOrBindingContext, extendContextCallback), rootNode, true); }; // Retrieving binding context from arbitrary nodes