Skip to content

Commit

Permalink
Allow template names to be selected as a function of the entire bindi…
Browse files Browse the repository at this point in the history
…ng context
  • Loading branch information
SteveSanderson committed Jun 26, 2012
1 parent 42da2d8 commit f2d175d
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 8 deletions.
17 changes: 11 additions & 6 deletions spec/templatingBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,15 @@ describe('Templating', {
value_of(innerObservable.getSubscriptionsCount()).should_be(0);
},

'Should be able to pick template as a function of the data item using data-bind syntax': function () {
var templatePicker = function(dataItem) {
'Should be able to pick template as a function of the data item using data-bind syntax, with the binding context available as a second parameter': function () {
var templatePicker = function(dataItem, bindingContext) {
// Having the entire binding context available means you can read sibling or parent level properties
value_of(bindingContext.$parent.anotherProperty).should_be(456);
return dataItem.myTemplate;
};
ko.setTemplateEngine(new dummyTemplateEngine({ someTemplate: "result = [js: childProp]" }));
testNode.innerHTML = "<div data-bind='template: { name: templateSelectorFunction, data: someProp }'></div>";
ko.applyBindings({ someProp: { childProp: 123, myTemplate: "someTemplate" }, templateSelectorFunction: templatePicker }, testNode);
ko.applyBindings({ someProp: { childProp: 123, myTemplate: "someTemplate" }, templateSelectorFunction: templatePicker, anotherProperty: 456 }, testNode);
value_of(testNode.childNodes[0].innerHTML).should_be("result = 123");
},

Expand Down Expand Up @@ -588,7 +590,7 @@ describe('Templating', {
value_of(testNode.childNodes[0].checked).should_be(true);
},

'Should be able to render a different template for each array entry by passing a function as template name': function() {
'Should be able to render a different template for each array entry by passing a function as template name, with the array entry\'s binding context available as a second parameter': function() {
var myArray = new ko.observableArray([
{ preferredTemplate: 1, someProperty: 'firstItemValue' },
{ preferredTemplate: 2, someProperty: 'secondItemValue' }
Expand All @@ -599,10 +601,13 @@ describe('Templating', {
}));
testNode.innerHTML = "<div data-bind='template: {name: getTemplateModelProperty, foreach: myCollection}'></div>";

var getTemplate = function(dataItem) {
var getTemplate = function(dataItem, bindingContext) {
// Having the item's binding context available means you can read sibling or parent level properties
value_of(bindingContext.$parent.anotherProperty).should_be(123);

return dataItem.preferredTemplate == 1 ? 'firstTemplate' : 'secondTemplate';
};
ko.applyBindings({ myCollection: myArray, getTemplateModelProperty: getTemplate }, testNode);
ko.applyBindings({ myCollection: myArray, getTemplateModelProperty: getTemplate, anotherProperty: 123 }, testNode);
value_of(testNode.childNodes[0]).should_contain_html("<div>template1output, firstitemvalue</div><div>template2output, seconditemvalue</div>");
},

Expand Down
4 changes: 2 additions & 2 deletions src/templating/templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
: new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));

// Support selecting template as a function of the data being rendered
var templateName = typeof(template) == 'function' ? template(bindingContext['$data']) : template;
var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;

var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
if (renderMode == "replaceNode") {
Expand All @@ -125,9 +125,9 @@
// This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
var executeTemplateForArrayItem = function (arrayValue, index) {
// Support selecting template as a function of the data being rendered
var templateName = typeof(template) == 'function' ? template(arrayValue) : template;
arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue));
arrayItemContext['$index'] = index;
var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
}

Expand Down

0 comments on commit f2d175d

Please sign in to comment.