0

Im trying to figure out the proper way to setup Knockout and Requirejs with multiple view models.

I have multiple view pages, each with it own view model, like:

  • page1.html - page1.js
  • page2.html - page2.js
  • many more

I have a main.js where I require these view models

require([
  "page1", 
  "page2"
, function ( page1, page2 ) {

  if( $("#page1").length ){
    ko.applyBindings(new page1());
  }
  if( $("#page2").length ){
    ko.applyBindings(new page2());
  } 

}); 

pagex.js

define(["jquery", "knockout"], function($, ko) {
  return function viewModel() { 
    console.log("foo");
  };
});

I have a constant problem with applying bindings multiple times so with jquery is the only way I have got it work but this cant be the recommended way?

I have also tried using if ko.applyBindings(new page1,(), document.getElementById('page1')) but it gives the same problem since I require all view models from main.. Even if I move the applybindings to the view models the same problem arise.

Per
  • 332
  • 3
  • 18
  • 1
    You could replace the body of the if in you main.js with this solution: http://stackoverflow.com/a/7342861/4065876. If you need to re-run ko.applyBindings(), try this: http://stackoverflow.com/a/15365693/4065876. Hope this help. – Jose Luis Dec 19 '16 at 08:35
  • @JoseLuis Thanks for the answer. However, the first solution will only work in a SPA (since im only loading a page at a time all applybindings that wont find the ID specified will fail nad give "multiplebinding"-error). Also I understand that it isnt a suggested way to use cleanNode? There must be a way of achieving this without using a "hack". – Per Dec 19 '16 at 09:28
  • Are there multiple `#pageN` elements in the DOM at the same time? Why can't you do `if ( /* ... */ ) { } else if ( ) { }` etc.? – user3297291 Dec 19 '16 at 09:30
  • @user3297291 No, only one page at a time. The jquery-if's im using now is working, whats the point of changing them? My point is, isnt there a best practise of doing this without if and else? Or is this the recommended way of dealing with multiple view models? – Per Dec 19 '16 at 09:54
  • 1
    The code you provided can only produce the mentioned error if (A) `main.js` is called multiple times, (B) multiple of `main`'s `if` statements return `true`, or (C) another file *also* calls `applyBindings`. "Best practice" is subjective... I'd suggest creating a `ParentViewModel` with an `observable` `pageVM` property. In your view, at the `#page` level, you bind using `with: pageViewModel`. – user3297291 Dec 19 '16 at 09:58
  • @PerThomasson Perhaps this could work: if ( $("#page1").length) {ko.applyBindings(new page1(), document.getElementById("page1")); } In 'main.js'. – Jose Luis Dec 19 '16 at 10:01
  • @user3297291 Sorry, I might have been unclear: the code I provided do work, its when I remove the jquery checks the multiple binding-error occur. Your suggestion sounds resonable =) Sort of the same as this answer: [link](http://stackoverflow.com/questions/9293761/knockoutjs-multiple-viewmodels-in-a-single-view#9294752)? – Per Dec 19 '16 at 10:24
  • 1
    Ah, I see. Yeah, it's like the answer you've linked. If you want to have *one* js bundle to be used on all your pages, it makes sense to put the logic that determines which viewmodel to use in the view itself, i.e. the html. Note that you might want to watch out with initialization logic that is executed but not used. E.g. if all your viewmodels load data from a server, but you're only using one, you might want to reconsider this approach... – user3297291 Dec 19 '16 at 10:28
  • @user3297291 This is just a prototype with local storage so it shouldn't be a problem. But shouldn't Require handle the initialization problem - only load data when its needed? – Per Dec 19 '16 at 11:19
  • 1
    If each page is the same template you could use a `foreach`: https://jsfiddle.net/timh06/rves162n/ -- similar to using `with`. Or if they are a lot different you could use components https://jsfiddle.net/timh06/fvy77rtg/. Best practice would definitely be to allow KO to handle the bindings for sub-viewmodels and to not re-apply unnecessarily. – Timh Dec 20 '16 at 20:44

0 Answers0