Search code examples
c#asp.net-mvc-4knockout.jsknockout-mvc

Knockout JS Observable Array and Model binding


I am trying to learn how to use knockout and have yet to find a simple example for what i am trying to achieve. I am simply wanting to bind a List inside of my mvc Model class to my viewModel for knockout. For instance if i have the model below..this is one class file.

public class PropaneMaintModel
{
   public List<PropaneMaintAssignment> PropaneMaint{get;set;}
   public List<string> LocationIds { get; set; }
   public int? SelectedLocation { get; set; }
}

public class PropaneMaintAssignment
{
    public int StoreNumber { get; set; }
    public int Tanks { get; set; }

    [Required(ErrorMessage="Tank Size must have a value")]
    [Range(0,10000,ErrorMessage="Tank Size must be between 0 and 10000.")]
    public int TankSize { get; set; }
}

How do i get the the list "PropaneMaint" to work with knockout binding? I need to add/remove from the list like the examples on knockouts site. My viewmodel is defined as below but it's not working.

 function propaneMaintViewModel() {
    var viewModel = this;

    viewModel.PropaneMaint = ko.observableArray([]);
    viewModel.addNew = function () {
        viewModel.PropaneMaint.push(
            {
                StoreNumber: 0,
                Tanks: 0,
                TankSize: 0
            }
       );
    }
}

ko.applyBindings(new propaneMaintViewModel());

Solution

  • Knockout doesn't have a direct binding to any c# model. What you can do is serialize your MVC viewmodel to a json object, then bind it. IE:

    function bindModels(arr) {
        var propaneMaintAssignments = new Array();
        for (var i = 0; i < arr.length; i++)
            propaneMaintAssignments.push(new PropaneMaintAssignment(arr[i]));
        return propaneMaintAssignments;
    }
    
    function PropaneMaintAssignment(model) {
        for(var property in model)
           this[property] = model[property];  //bind all properties
    }
    
    var json = @Html.Raw(new JavaScriptSerializer().Serialize(Model.PropaneMaint)); //results in an array
    var list = bindModel(json);  //makes an array of named objects
    viewModel.PropaneMaint(list);  //adds that array of named objects to your observableArray