Multiple ViewModel in the same View


If you have several View Models separated in partial Views and you want to use both in a main View you can do this creating each context with a specific name like var ko = Html.CreateKnockoutContext("HelloWorldViewModel"); and applying only a specific container id for avoid viewmodel overwriting: @ko.Apply(Model,"js-helloWorldViewModelWrapper")

In this way you can have two different view models in the same View even if the view models has the same properties.

Live example

You've clicked times
That's too many clicks! Please stop before you wear out your fingers.

First name:

Last name:

Hello, !


public class MultipleViewModelModel
    public ClickCounterModel ClickCounterModel { get; set; }
    public HelloWorldModel HelloWorldModel { get; set; }


@using PerpetuumSoft.Knockout
@model KnockoutMvcDemo.Models.MultipleViewModelModel
@Html.Partial("PartialClickCounterViewModel", Model.ClickCounterModel)
<hr />
@Html.Partial("PartialHelloWorldViewModel", Model.HelloWorldModel)


public class MultipleViewModelController : BaseController
    public ActionResult Index()
        InitializeViewBag("Multiple ViewModel in the same View");
        var model = new MultipleViewModelModel
                          ClickCounterModel = new ClickCounterModel(),
                          HelloWorldModel = new HelloWorldModel
                              FirstName = "Steve",
                              LastName = "Sanderson"
        return View(model);

Html (autogenerated)

<div id="js-clickCounterViewModelWrapper">
  <div>You've clicked <span data-bind="text : NumberOfClicks"></span> times</div>
  <button data-bind="click : function() {executeOnServer(ClickCounterViewModel, &#39;/ClickCounter/RegisterClick&#39;);},disable : HasClickedTooManyTimes">Click me</button>
  <div data-bind="visible : HasClickedTooManyTimes">
    That's too many clicks! Please stop before you wear out your fingers.
  <button data-bind="click : function() {executeOnServer(ClickCounterViewModel, &#39;/ClickCounter/ResetClicks&#39;);}">Reset clicks</button>

<script type="text/javascript"> 
var ClickCounterViewModelJs = {"NumberOfClicks":0};
var ClickCounterViewModel = ko.mapping.fromJS(ClickCounterViewModelJs); 
ClickCounterViewModel.HasClickedTooManyTimes = ko.computed(function() { try { return ((this.NumberOfClicks() < 3) == false)} catch(e) { return null; }  ;}, ClickCounterViewModel);
ko.applyBindings(ClickCounterViewModel, document.getElementById('js-clickCounterViewModelWrapper'))

<hr />
<div id="js-helloWorldViewModelWrapper">
  <p>First name: <input data-bind="value : FirstName" name="FirstName" type="text" /></p>
  <p>Last name: <input data-bind="value : LastName" name="LastName" type="text" /></p>
  <h2>Hello, <span data-bind="text : FullName"></span>!</h2>

<script type="text/javascript"> 
var HelloWorldViewModelJs = {"FirstName":"Steve","LastName":"Sanderson"};
var HelloWorldViewModel = ko.mapping.fromJS(HelloWorldViewModelJs); 
HelloWorldViewModel.FullName = ko.computed(function() { try { return ((this.FirstName() + ' ') + this.LastName())} catch(e) { return null; }  ;}, HelloWorldViewModel);
ko.applyBindings(HelloWorldViewModel, document.getElementById('js-helloWorldViewModelWrapper'))