Multiple ViewModel in the same View

Description

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, !

Model

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

Razor

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

Controller

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>
  </div>
</div>

<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'))
</script>

<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>
</div>

<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'))
</script>