Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KO cannot find template with ID

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.

  • I'm using KO in the context of Durandal, though this shouldn't make a difference.
  • Tried declaring the template before usage, didn't help.
  • Someone else ran into the same thing with no solution either

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.

like image 928
Kal_Torak Avatar asked Mar 28 '13 18:03

Kal_Torak


People also ask

How does Ko identify the template block that needs to be rendered?

Shorthand syntax: If you just supply a string value, KO will interpret this as the ID of a template to render. The data it supplies to the template will be your current model object.

How do I use knockout js in HTML?

It is very easy to use KnockoutJS. Simply refer the JavaScript file using <script> tag in HTML pages. A page as in the following image will be displayed. Click on download link and you will get the latest knockout.

What is data binding in knockout JS?

Knockout's declarative binding system provides a concise and powerful way to link data to the UI. It's generally easy and obvious to bind to simple data properties or to use a single binding.


2 Answers

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,

  • Mixing knockout templates with durandal compose
  • knockout can't find templates inside of views
like image 199
Kal_Torak Avatar answered Sep 24 '22 21:09

Kal_Torak


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");
}
like image 42
user2246674 Avatar answered Sep 21 '22 21:09

user2246674