CLiown
CLiown

Reputation: 13843

KnockOutJS - Multiple ViewModels in a single View

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 :)

Upvotes: 204

Views: 86874

Answers (5)

gyula.nemeth
gyula.nemeth

Reputation: 867

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.

Upvotes: 0

Janith Widarshana
Janith Widarshana

Reputation: 3483

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.

Upvotes: 24

John Papa
John Papa

Reputation: 22298

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.

Upvotes: 150

sanatgersappa
sanatgersappa

Reputation: 4357

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.

Upvotes: 291

Sergey Zwezdin
Sergey Zwezdin

Reputation: 386

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

Upvotes: 4

Related Questions