Wrapcode

Communication between multiple View Models in KnockoutJS (MVVM), the right approach!

| 5 min read

Big fat View Model

KnockoutJS is a beautiful JavaScript framework that helps you to create responsive and data rich user interface without making the JavaScript code dirty. When you start learning KnockoutJS, you tend to make habit of creating single a View Model and binding it globally or to one particular DOM and play with it.

Once you start diving deep, you will realize, single view model is not enough for developing enterprise applications. It does not help you maintaining the modularity of an application. Bigger the application gets, complexity of the view model increases. You will literally give up as the code will become hard to maintain and even harder to test.

Goodness of multiple view models

Why one should use multiple view models? Answer is simple, it maintains the modularity. Multiple view models act as modules. You basically divide big problem into small modules which are reusable and easily extensible. You preserve ability to maintain an application by decoupling the components to the most granular level. The app flow becomes so good with introduction of multiple view models in your app.

However, there is a major and most discussed problem with this approach on KnockoutJS section of StackOverflow, Knockout forums (common question with MVVM pattern in general). The communication between multiple view models. Surprisingly, this problem has not been addressed or discussed at all in KO documentation even though people face it quite often. I end up helping at least couple of KnockoutJS users / developers on Stack Overflow having the same problem.

Yes, we don't have out of the box and easy to use solution on communication between multiple view models which are bound in a single viewport but with different DOM elements like the code below.

var self = this;
self.firstName = ko.observable();
self.lastName = ko.observable();
self.fullName = ko.computed(function(){
return self.firstName + " " + self.lastName;
});
};
var viewModel2 = function(){
var self = this;
self.premium = ko.observable();
};
ko.applyBindings(new viewModel1(), document.getElementById("container1"));
ko.applyBindings(new viewModel2(), document.getElementById("container2"));
view raw vm1.js hosted with ❤ by GitHub

There are two correct approaches of maintaining communication between multiple view models.

  1. Maintaining master view model
  2. Introducing pub-sub

Maintaining master View Model

First way of achieving communication between multiple view models is to introduce master view model.

// view model 1 definition
var viewModel1 = function(){
this.firstName = ko.observable("Wrapcode");
this.messageForVM2 = ko.observable("Hello from first view model");
this.message = ko.observable("Hello this is vm1")
};
//view model 2 definition
var viewModel2 = function(vm1){
this.firstName = ko.observable(vm1.firstName());
this.message = ko.observable(vm1.messageForVM2());
};
//master view model with instances of both the view models.
var masterVM = (function(){
this.viewModel1 = new viewModel1(),
this.firstName = "Rahul",
this.viewModel2 = new viewModel2(this.viewModel1);
})();
ko.applyBindings(masterVM)
view raw vm2.js hosted with ❤ by GitHub

Live action on JSFiddle : https://jsfiddle.net/rahulrulez/paxnd6uz/1/