KnockOutJS - Multiple ViewModels in a single View

Mvvmknockout.jsData BindingKnockout Mapping-Plugin

Mvvm Problem Overview


I'm thinking that my application is getting quite large now, too large to handle each View with a single ViewModel.

So I'm wondering how difficult it would be to create multiple ViewModels and load them all into a single View. With a note that I also need to be able to pass X ViewModel data into Y ViewModel data so the individual ViewModels need to be able to communicate with each other or at least be aware of each other.

For instance I have a <select> drop down, that select drop down has a selected state which allows me to pass the ID of the selected item in the <select> to another Ajax call in a separate ViewModel....

Any points on dealing with numerous ViewModels in a single View appreciated :)

Mvvm Solutions


Solution 1 - Mvvm

Knockout now supports multiple model binding. The ko.applyBindings() method takes an optional parameter - the element and its descendants to which the binding will be activated.

For example:

ko.applyBindings(myViewModel, document.getElementById('someElementId'))

This restricts the activation to the element with ID someElementId and its descendants.

See documentation for more details.

Solution 2 - Mvvm

If they all need to be on the same page, one easy way to do this is to have a master view model containing an array (or property list) of the other view models.

masterVM = {
    vmA : new VmA(),
    vmB : new VmB(),
    vmC : new VmC(),
}

Then your masterVM can have other properties if needed, for the page itself. Communication between the view models would not be difficult in this situation as you could relay through the masterVM, or you could use the $parent / $root in bindings, or some other custom options.

Solution 3 - Mvvm

This is my answer after completing very large project with lots of ViewModels in single view.

Html View

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div id="container1">
        <ul>
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>
    
    <div id="container2">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>
    
    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/knockout-3.0.0.js"></script>
    <script src="js/DataFunction.js"></script>
    <script src="js/Container1ViewModel.js"></script>
    <script src="js/Container2ViewModel.js"></script>

</body>
</html>

For this view I'm creating 2 view models for id=container1 and id=container2 in two separate javascript files.

Container1ViewModel.js

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");
    
} 

Container2ViewModel.js

function Container2ViewModel() {
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");
    
}

Then after these 2 viewmodels are registering as separate viewmodels in DataFunction.js

var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }
    
    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});

Like this you can add any number of viewmodels for separate divs. But make sure do not create separate view model for a div inside registered div.

Solution 4 - Mvvm

Check MultiModels plugin for Knockout JS - https://github.com/sergun/Knockout-MultiModels

Solution 5 - Mvvm

We use components to achieve that. (http://knockoutjs.com/documentation/component-overview.html)

For example, we have this component library we are developing: https://github.com/EDMdesigner/knobjs

If you dig into the code, you will see that for example we reuse the knob-button component in several places.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCLiownView Question on Stackoverflow
Solution 1 - MvvmsanatgersappaView Answer on Stackoverflow
Solution 2 - MvvmJohn PapaView Answer on Stackoverflow
Solution 3 - MvvmJanith WidarshanaView Answer on Stackoverflow
Solution 4 - MvvmSergey ZwezdinView Answer on Stackoverflow
Solution 5 - Mvvmgyula.nemethView Answer on Stackoverflow