Nika Javakhishvili
Nika Javakhishvili

Reputation: 462

Load knockout components dynamically

This is my html :

<a href="#page1">page 1</a>
<a href="#page2">page 2</a>

This is my js :

define(['jquery', 'knockout'], function ($, ko) {


     ko.components.register('page1', {
    require: 'App/Controllers/page1'
});
ko.components.register('page2', {
    require: 'App/Controllers/page2'
});

    window.onhashchange = function () {
        var hash = location.hash.replace('#', '');
        $('#body').html('<' + hash + '></' + hash + '>'); //hash = page1 or page2
    }

    ko.applyBindings();
})

However, when hash changes, components doesn't load and body content is simply: <page1></page1> or second page. If i would change my js like this :

define(['jquery', 'knockout'], function ($, ko) {

    ko.components.register('page1', {
    require: 'App/Controllers/page1'
});
ko.components.register('page2', {
    require: 'App/Controllers/page2'
});

    $('#body').html('<page1></page1>');

    ko.applyBindings();
})

It works fine

Upvotes: 5

Views: 4861

Answers (1)

Roy J
Roy J

Reputation: 43881

Replacing the body html is going to leave everything unbound. You should not use cleanNode; it is a kludge.

If you want to change which component is being used, use the component binding on the containing tag (body is fine), using an observable that contains the desired component. Here's an example, using a timer to change the template.

ko.components.register('page1', {
    template:'page1 template'
});
ko.components.register('page2', {
    template:'page2 template'
});
 
vm = {page:ko.observable('page1')};
ko.applyBindings(vm);

setTimeout(function () {
    vm.page('page2');
}, 1500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="component: page"></div>

Upvotes: 8

Related Questions