mhu
mhu

Reputation: 18051

Exception occurs in ie8 when dynamically updating Knockoutjs template

I use ajax to retrieve a partial HTML document to use as a Knockout template.

HTML:

<script type="text/html" id="LoadingTemplate">Loading...</script>
<script type="text/html" data-bind="attr: {'id': DynamicTemplateID}, html: ContentHTML></script>

<div class="main-page" data-bind="template: TemplateID"></div>

Script (partial):

self.TemplateID = ko.observable("LoadingTemplate");
self.DynamicTemplateID = ko.observable(GenerateUUID());

self.ContentHTML = ko.observable();    
ko.computed(function () {
    var url = self.ContentURL();
    self.GetContent(url, function (html) {
        self.ContentHTML(html);
        self.TemplateID(self.DynamicTemplateID());
    });
});
  1. Initially the <div> will show: 'Loading'
  2. The id attribute of the dynamic template is set to the generated ID
  3. GetContent() performs an ajax call to retrieve the content
  4. When the ajax call finishes the callback function is called
  5. The observable ContentHTML is updated with the html
  6. The observable TemplateID is set to the generated ID
  7. The <div> is updated by ko

In Firefox this works like a charm, but IE8 throws an exception: Error: Unexpected call to method or property access. while updating the dummy <script> tag with the loaded template.

The error is throw by jQuery.html(). First elem.innerHTML = value; fails, which is catched then this.empty().append( value ) fails, which gives the exception.

Partial 'stack trace':

this.appendChild( elem );    => callback function in jquery.append (v1.7.2 line 5847)
jquery.domManip
jquery.append
jquery.html
ko.utils.setHtml
ko.bindingHandlers.html.update
ko.applyBindingsToNodeInternal
ko.dependentObservable.evaluateImmediate

What could be the problem? Is it there a (known) IE8 problem with updating <script> tags?
Is there another way to 'store' templates inside the html page for ko to use (I prefer to use the ko native templating!)?

Upvotes: 0

Views: 1275

Answers (1)

mhu
mhu

Reputation: 18051

I've solved it using this article on knockmeout.net:

Updated HTML (removed the dynamic <script> tag):

<script type="text/html" id="LoadingTemplate">Loading...</script>
<div class="main-page" data-bind="template: TemplateID"></div>

Updated script (appends the script tag after download of the template):

self.TemplateID = ko.observable("LoadingTemplate");
self.dynamicTemplateID = GenerateUUID();

ko.computed(function () {
    var url = self.ContentURL();
    self.GetContent(url, function (html) {
        $("body").append('<script type="text/html" id="' + self.dynamicTemplateID + '">' + html + '</script>');

        self.TemplateID(self.dynamicTemplateID);
    });
});

This is a little bit less the ko-way but works across all browsers.

Upvotes: 1

Related Questions