Frage

Cannot get my brain around how to implement knockout for the following ASP.NET MVC 4 nested view model :

public class MyProfile
{
  public string Name { get; set; }

  public IList<VM1>   List1    { get; set; }
  public IList<VM2>   List2    { get; set; }
  ....
  public IList<VM10>  List10    { get; set; }
}
// example of VM view model
public class VM1
{
   IList<Label> Labels { get; set; }
   IList<Contact1> Contact1 { get; set; }
}

In the view I accept model like this:

@model MyProfile

@using (Html.BeginForm("Index", "Profile", FormMethod.Post, new { id = "profileEditorForm" }))
{

  @Html.ValidationSummary(false)
    <fieldset>
  <legend>User's data</legend>
  <label for="name">Name:</label>
  <input type="text" id="name" name="name" class="required" data-bind="value: Name"/>
    </fieldset>

 @Html.EditorFor(m => @Model.List1, "List1") @* Editpr model for List1*@
 @Html.EditorFor(m => @Model.List2, "List2")
 .....
 @Html.EditorFor(m => @Model.List10, "List10")

 <p>
   <input type="submit" value="Save" data-bind="enable: (List1().length > 0) && (List2().length > 0) && ...(List10().length > 0)" />
<a href="/">Cancel</a>
 </p>
}

The EditorTemplate for List1 would look like this with multiple questions in:

@model IList<FiveW.ViewModels.List1>

<fieldset>

  <table>
    <tbody data-bind="foreach: Contact1">
      <tr>
        <td>
          <label>Email:</label></td>
        <td>
          @* How do you put combobox here with labels here?
          How do you tie selected label to selected property on your Contact1 object *@
          @*<select data-bind="options: Labels, optionsText: 'LabelName', value: selectedLabel, optionsCaption: 'Choose...'"></select></td>
        <td>
          <input type="text" data-bind="value: Name, uniqueName: true" class="required" /></td>
        <td>
          <a href="#" data-bind="click: function() { viewModel.removeContact1(this); }">Delete</a></td>
      </tr>
    </tbody>
  </table>


  <button data-bind="click: addContact1">Add Contact1</button>

</fieldset>

Edit

VM1 through VM10 are the same except the validation logic, so I have to make them different classes (unfortunately, since it TONS of repetition in models, and in the views).

Client side - this is what I am asking about: I need to pass from ASP MVC models containing nested lists and have them presented on the client with knockout (I found it to do best pertaining dynamic lists). It is something similar to gmail contacts - you have home/work/mobile/fax phone - so one list is label for the phone (what phone is it) and should be presented as combobox, another one is dynamic lists of phones that can increase as per user clicks.

End edit

  1. I don't understand how to create a knockout viewModel from this nested model, obviously Name should be part of it, but the rest are lists and they also contain lists.

  2. How to map it?

  3. how to handle it (one goes into dropdownlist that will be the label of the other list, which is variable in length - the only reason to use knockout here).?

  4. once filled out, how to put it all together and ship back to controller action?

  5. how to write that editor model when label is dropdownlist (or combobox) of labels for the name (example is: [label]home/work [name]email, [label]mobile/home/car [name]phone)

If it was simple class with IList inside - its like here. Problem is that there are lists inside lists, Knockout demands that everything is observable, not sure how to express in java script this nesting model.

Please help. Thanks in advance!

War es hilfreich?

Lösung 2

Had to rephrase the question to single out the issue I had, rather than asking general question like here.

Huge thanks for efforts to answer, unfortunately I find that if you don't formulate your questions properly you get respectively common (non specific) responses. So its my bad.

Because of large number of people interested in the question I posed (there were 5 upvotes in first 3 hours), here is where I asked the same question with stress on specific issues I had and got the right answer and got my knockout to knockout again.

ASP.NET with Knockout variable length list with combobox - how to bind?

Hope this helps somebody as it helped me & thanks again!

Andere Tipps

I wouldn't use mapping. I would just declare the ViewModel client-side like this:

//I'm asuming the properties for Label and Contact, this is just for example purposes
function LabelViewModel(){
    var self = this;
    self.LabelName = ko.observable();
}
function Contact(){
    var self = this;
    self.Name = ko.observable();
    self.LastName = ko.observable();
}

//This is the definition for the List. I believe it shouldn't matter that the class names are different as long as the structure is the same
function ListViewModel(){
    var self = this;
    self.Labels = ko.observableArray();
    self.Contacts = ko.observableArray();
}

function MainViewModel(){
    var self = this;
    self.Name = ko.observable();
    self.List1 = ko.observableArray();
    //....
    self.List10 = ko.observableArray();
}


$(document).ready(function(){
    var viewModel = new MainViewModel(@Html.Raw(JsonConvert.SerializeObject(Model)));
    ko.applyBindings(viewModel);
});

Then, on submit I would try to submit from jquery instead of doing an http post directily:

var viewModelJs = ko.toJS(ko.utils.unwrapObservable(viewModel));
var parameters = JSON.stringify({vm: viewModelJs});

$.ajax('http://yourControllerUrlHere', {
    data: parameters,
    type: "POST",
    contentType: "application/json",
    dataType: "json",
    success: function (result) {
        console.log('Submitted ok');
    },
    error: function (error) {
        console.log(error);
    }
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top