KO cannot find template with ID
Asked Answered
G

2

6

I've used Knockout templates before, so I'm not sure why this isn't working for me. I tried two different styles of ko markup, neither work.

<!-- more nesting levels -->
<div class="cal-day-tps" data-bind="foreach: timePeriods">
    <div class="cal-day-tp-cont">

        <div data-bind="template: { name: 'tp-ed-templ', data: $data }"></div>

        //both of these methods fail
        <!-- ko template: { name: 'tp-ed-templ', data: $data } -->
        <!-- /ko -->

    </div>
</div>    
<!-- /more nesting levels -->


<script type="text/html" id="tp-ed-templ">
 <!-- bunch of markup -->
</script>

I just get the error "Cannot find template with ID tp-ed-templ".

Probably just a typo, but I haven't been able to find it.

It seems to be an issue with Durandal, not Knockout.

I tried some extremely simple cases in vanilla durandal setups, and it still does the same thing. Even tried putting the script in the same nested location as the binding, no dice.

Googolplex answered 28/3, 2013 at 18:4 Comment(3)
Where is your ko.applyBindings() being called?Bedroll
Yea, can we see more code? jsFiddle?Sotos
The only thing I can think of without seeing more code is that the binding is being called before the entirety of the DOM is loaded and ready.Bedroll
G
10

The short answer: You can't currently use Knockout templates inside of Durandal. However, as nemesv pointed out, if you put your named template outside of Durandal, ko is able to find them. For example, anywhere outside of the <div id="applicationHost"></div> element.

The other workarounds are to either use Durandal's compose functionality, or just inline the templates as anonymous.

Knockout templates will probably be supported in the near future.

I finally dug these answers up on the Durandal google group,

Googolplex answered 28/3, 2013 at 19:40 Comment(3)
If you put your named template outside of Durandal to the index.cstml .It will work, KO can find it there.Overwrought
I had the same question early on, and was advised to look closely into using Durandal's ko.compose binding to accomplish my task. I have found that ko.compose meets most of my templating needs and works very smoothly with Durandal. You can just specify a template name (I think Durandal considers it a area name) and the composition engine will load the html and bind it to the current model.Locarno
You are correct sir, I was wrong. I had no idea you couldn't use templates inside of views.Celom
U
3

The issue is that the KO template element must exist in the DOM before the Durandal view is bound. This is because the view is bound before it is inserted into the DOM so any contained templates cannot be resolved by ID.

Using a function that returns an observable can be used to later re-trigger a template binding .. it works, but is wonky. (An if binding could be used for similar effect.)

// bind to this in markup:
//   <div data-bind="template: {name: $root.templateName, .. }">
vm.templateName = function () {
   return vm.TemplateId();
};

// Changing this will trigger an observable in the KO template binding;
// don't ask me why we have to pass in a function to 'name' ..
vm.TemplateId = ko.observable("dummy-template-id-that-exists");

// After the view is attached the correct template element is in the DOM
// so we can trigger the template to (re-)bind and it will find it.
function viewAttached () {
   vm.TemplateId("the-real-template-id");
}
Umber answered 22/5, 2013 at 23:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.