Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockoutjs working with multiple view models

I am trying to get Knockout js working with jQueryMobile and am hitting a few problems when moving between pages.

I would like to try and keep the page transitions in JQM and therefore I would like to use either the multiple page option (multiple pages defined in one html file) or load the additional pages into the DOM as detailed in default AJAX behaviour section of the documentation.

JQM Page Transition Documentation

I have two individual Knockoutjs pages working both with a separate view model on each. Both pages work perfectly until I attempt to link them together through JQM.

Whichever page I attempt to load I get an error relating to a mapping on the other page. I can only assume that both pages are loaded into the single DOM and when Knockout applies the bindings it is looking for properties that do not exist.

I have attempted to make a jsFiddle to demonstrate this.

JQM - Knockout Fiddle

I am new to both JQM and Knockout so any help appreciated. If I am taking completely the wrong approach then I would appreciate someone pointing me in the right direction.

Would I be better attempting to use one ViewModel for the whole site? If not how can I use Knockoutjs with JQM?

like image 962
fluent Avatar asked Jan 09 '12 21:01

fluent


People also ask

Can we have multiple knockout models on a single page?

Binding Multiple ViewModels Whether you are simply looking to keep your ViewModels nice and clean, or you have a shared ViewModel that appears on each page, there will come a time when you wish to bind multiple ViewModels on a single page. Knockout makes this quite easy.

What is KnockoutJS used for?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.

How do you activate a KnockoutJS model?

Activating Knockout To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.


2 Answers

One "master" view model for the whole site would be acceptable. Then, you could do something like this:

var masterViewModel = {
   viewModelOne: ...,
   viewModelTwo: ...
}

Alternately, you can call the .applyBindings overload to apply bindings to individual elements, rather than the whole DOM:

ko.applyBindings(new modelOne("Test", "One"), $("#one")[0]);
ko.applyBindings(new modelTwo("Test", "Two"), $("#two")[0]);

Personally, I'd recommend the second approach.

like image 91
Judah Gabriel Himango Avatar answered Sep 19 '22 20:09

Judah Gabriel Himango


I'm currently using jQuery Mobile 1.3.1 and Knockout 2.2.1 and tried many approaches before finding a (hopefully) permanent solution to this problem. The hard part is figuring out when to apply bindings. When I used jQuery's ready function, that didn't work. I found in the jQM documentation to bind upon the pageinit event callback instead of the document ready function. However, this callback is fired off every time a page is rendered for the first time so if you have 5 jQM pages, it could be fired off 5 times and you're only supposed to apply KO bindings once.

The solution I eventually used was the following:

$(document).bind('pageinit', function (e) {
    var pageId = e.target.id;

    for (var i in VIEW_MODELS) {
        var vm = VIEW_MODELS[i];
        if (pageId == vm.View) {
            ko.applyBindings(vm, document.getElementById(vm.View));
        }
    }
});

What this is doing is every time a jQM page is initially rendered, it searches through my view models to find the view model associated with the upcoming view and applies bindings. Since pages are only initialized the first time they are rendered, it will apply ko bindings upon that first rendering and never again.

So far this is working for me but I'd be curious to hear other people's opinions or solutions to using jQM multi-page templates with Knockout.

like image 41
Cameron Askew Avatar answered Sep 21 '22 20:09

Cameron Askew