Gene Golovchinsky
Gene Golovchinsky

Reputation: 6131

calling template from a knockoutjs binding

In a knocoutjs binding, I would like to generate some HTML and it to an element. This HTML is identical to a template I already have. I tried doing the obvious, and calling the template binding from another binding, but I am getting an error as shown below.

My call

// doc is a parameter to the method
var $assessments = $('div');
var docfcn = function() { return doc; }
var defaultAllBindingContexts = function() { return {}; }
ko.bindingHandlers.template.update($assessments, function() {return {name: 'assessmentControls', data: docfcn};}, defaultAllBindingContexts, doc);

The error:

Uncaught TypeError: Cannot call method 'createChildContext' of undefined
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2864
getDocDescriptionbindings.js:627
ko.bindingHandlers.rankeddoc.updatebindings.js:667
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
ko.renderTemplateForEach.activateBindingsCallbackknockout-2.0.0.debug.js:2794
ko.utils.setDomNodeChildrenFromArrayMappingknockout-2.0.0.debug.js:3100
ko.renderTemplateForEach.ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:2809
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateForEachknockout-2.0.0.debug.js:2799
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2859
ko.bindingHandlers.foreach.updateknockout-2.0.0.debug.js:2452
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.bindingHandlers.with.updateknockout-2.0.0.debug.js:2390
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
ko.renderTemplateForEach.activateBindingsCallbackknockout-2.0.0.debug.js:2794
ko.utils.setDomNodeChildrenFromArrayMappingknockout-2.0.0.debug.js:3100
ko.renderTemplateForEach.ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:2809
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateForEachknockout-2.0.0.debug.js:2799
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2859
ko.bindingHandlers.foreach.updateknockout-2.0.0.debug.js:2452
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.bindingHandlers.with.updateknockout-2.0.0.debug.js:2390
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
applyBindingsToDescendantsInternalknockout-2.0.0.debug.js:1755
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1776
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.bindingHandlers.with.updateknockout-2.0.0.debug.js:2390
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
applyBindingsToNodeInternalknockout-2.0.0.debug.js:1855
applyBindingsToNodeAndDescendantsInternalknockout-2.0.0.debug.js:1773
ko.applyBindingsknockout-2.0.0.debug.js:1887
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2700
invokeForEachNodeOrCommentInParentknockout-2.0.0.debug.js:2682
ko.activateBindingsOnTemplateRenderedNodesknockout-2.0.0.debug.js:2699
executeTemplateknockout-2.0.0.debug.js:2739
ko.renderTemplate.ko.dependentObservable.disposeWhenknockout-2.0.0.debug.js:2769
evaluateInitialknockout-deferred-updates.js:241
newComputedknockout-deferred-updates.js:281
ko.renderTemplateknockout-2.0.0.debug.js:2759
ko.bindingHandlers.template.updateknockout-2.0.0.debug.js:2866
ko.bindingHandlers.with.updateknockout-2.0.0.debug.js:2390
ko.dependentObservable.disposeWhenNodeIsRemovedknockout-2.0.0.debug.js:1848
evaluateImmediateknockout-deferred-updates.js:225
evaluatePossiblyAsyncknockout-deferred-updates.js:200
ko.subscribable.fn.notifySubscribersknockout-2.0.0.debug.js:809
ko.utils.arrayForEachknockout-2.0.0.debug.js:60
ko.subscribable.fn.notifySubscribersknockout-2.0.0.debug.js:805
ko.observable.observable.valueHasMutatedknockout-2.0.0.debug.js:882
observableknockout-2.0.0.debug.js:871
selectViewquerium.js:694
Array.eachquerium.js:108
selectViewquerium.js:691
PaginatedView.selectSummaryViewModel.js:35
ko.bindingHandlers.event.initknockout-2.0.0.debug.js:1949
c.event.handlejquery-1.4.2.min.js:55
c.event.add.j.handle.o

What do I need to do to trigger the template correctly?

Thanks,

Gene

UPDATE 9 Mar 2012, 1:52 PST:

I implemented the solution suggested by @madcapnmckay as follows:

    ko.renderTemplate('assessmentControls', doc, {}, $assessments, "replaceNode");

and am now getting an error from the template (which is progress!):

Uncaught Error: Unable to parse bindings.
Message: ReferenceError: $parent is not defined;
Bindings value: assessment: 'REL', css: {selected: isRelevant}, button:{text: false, primary: 'assessment REL'}, filters: $parent.filters

The template in question looks like this:

<script id="assessmentControls" type="text/html">
    <div class="block docicons">
        <button title="Save document" 
            style="margin-top: 10px" 
            data-bind="assessment: 'REL', css: {selected: isRelevant}, button:{text: false, primary: 'assessment REL'}, filters: $parent.filters"></button> 
        <button title="Skip in future results" 
            data-bind="assessment: 'NOT_REL', css: {selected: isNotRelevant}, button:{text: false, primary: 'assessment NOT_REL'}, filters: $parent.filters"></button>
    </div>
</script>

So now the issue is how to specify the parent so that the template behaves as expected.

UPDATE 9 Mar 2012 5:35 PM:

Added a jsfiddle to illustrate above error.

Upvotes: 2

Views: 5052

Answers (1)

madcapnmckay
madcapnmckay

Reputation: 15984

To render a template from within a binding you can use the ko.renderTemplate method.

ko.renderTemplate(template, dataOrBindingContext, options, 
    targetNodeOrNodeArray, renderMode)

e.g

ko.renderTemplate("contextMenuTemplate", config, 
    { templateEngine: templateEngine }, menuContainer, "replaceNode");

Hope this helps.

EDIT

As John Earls stated in the comments. You can pass either binding data or a bindingContext into the method. The template is bound to whatever you pass in. It's up to you to create that context if you wish to have access to $parent etc.

Upvotes: 4

Related Questions