【问题标题】:ASP.NET MVC with nested view model and Knockout具有嵌套视图模型和淘汰赛的 ASP.NET MVC
【发布时间】:2013-02-19 05:40:01
【问题描述】:

想不通如何为以下 ASP.NET MVC 4 嵌套视图模型实现淘汰赛:

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; }
}

在视图中我接受这样的模型:

@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>
}

List1 的 EditorTemplate 如下所示,其中包含多个问题:

@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>

编辑

除了验证逻辑之外,VM1 到 VM10 是相同的,所以我必须将它们设为不同的类(不幸的是,因为它在模型和视图中重复了很多次)。

客户端 - 这就是我要问的: 我需要从包含嵌套列表的 ASP MVC 模型中传递,并让它们通过淘汰赛呈现在客户端上(我发现它在动态列表方面做得最好)。 它类似于 gmail 联系人 - 你有家庭/工作/移动/传真电话 - 所以一个列表是电话的标签(它是什么电话)并且应该显示为组合框,另一个是可以增加的电话动态列表根据用户点击次数。

结束编辑

  1. 我不明白如何从这个嵌套模型创建一个淘汰视图模型,显然 Name 应该是它的一部分,但其余的是列表,它们也包含列表。

  2. 如何映射?

  3. 如何处理(一个进入下拉列表,将成为另一个列表的标签,长度可变 - 此处使用敲除的唯一原因)。?

  4. 填写后,如何将所有内容放在一起并发送回控制器操作?

  5. 当标签是名称标签的下拉列表(或组合框)时,如何编写该编辑器模型(例如:[label]home/work [name]email、[label]mobile/home/car [name ]电话)

如果它是一个简单的类,里面有IList - 它就像here。问题是列表中有列表,Knockout 要求一切都是可观察的,不知道如何在 java 脚本中表达这种嵌套模型。

请帮忙。提前致谢!

【问题讨论】:

  • 嘿,你的客户端视图模型声明在哪里?也许我们可以从那里开始
  • 每个 List 元素是不同的类型吗?我看到你已经声明了 VM1,还会有 VM2、VM3、VM...n 作为类声明吗?这些是不同的还是你可以创建一个通用的类列表类型并且只有 10 个实例?
  • 查看编辑。除了数据注释(或流畅验证的验证规则)之外,VM1 是相等的。客户端是我要问的。两个列表 - 一个是组合框(工作/家庭),另一个是组合框(电话/电子邮件/地址/等)。如何在 Knockout 中表达...谢谢
  • 如果类相同(属性名称和类型一致),那么您只需要一个子 ViewModel。我写一个例子,试着回答这五点
  • 非常感谢,这为我澄清了一些事情,但我最关心的问题仍然没有解决 - 如何将组合框放在可以选择并发回服务器的编辑器模板中以说“Contact1”例如,类型为“Label2” - 可以在编辑器模板的 ComboBox 中选择标签。谢谢!

标签: asp.net-mvc knockout.js viewmodel knockout-2.0 asp.net-mvc-viewmodel


【解决方案1】:

我不会使用映射。我会像这样声明 ViewModel 客户端:

//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);
});

然后,在提交时,我会尝试从 jquery 提交,而不是直接进行 http 发布:

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);
    }
});

【讨论】:

  • 除了主模型之外,我主要关注我使用的 EditorTemplates:List1 等到 List10。他们所做的是在附加的编辑中 - 基本上显示下拉菜单(最好是组合框),标签作为选择选项,主要输入文本作为联系人#。例如,我使用了 gmail 联系信息:Contact1 是电子邮件,其标签可以在“工作”、“家庭”或“自定义”之间选择... - 如何表达组合框及其内容(email@domain.com 被标记“家”电子邮件)-希望您能理解。假设所有属性都是字符串。查看其他编辑 - 我添加了 EditorTemplate。谢谢你!
  • 您在数据绑定中说“值:名称,唯一名称:真”。您需要传递整个路径,这就是为什么我告诉您寻找一种从主视图传递 HtmlAttributes 对象的方法。而不是 value:Name 它应该类似于 'List1()[0].PropertyYouNeedToAccess'
  • 这是一个类似的解决嵌套绑定问题的答案:stackoverflow.com/questions/7466423/…
【解决方案2】:

不得不改写问题以找出我遇到的问题,而不是像这里这样问一般性问题。

非常感谢您为回答所做的努力,不幸的是,我发现如果您没有正确地提出您的问题,您会分别得到常见(非特定)的回答。所以这是我的错。

由于很多人对我提出的问题感兴趣(前 3 小时内有 5 人赞成),所以我在这里问了同样的问题,强调我遇到的具体问题并得到了正确的答案并被淘汰了再次淘汰。

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

希望这对某人有所帮助,因为它帮助了我,再次感谢!

【讨论】:

    猜你喜欢
    • 2013-05-31
    • 1970-01-01
    • 2015-08-17
    • 2013-07-08
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    相关资源
    最近更新 更多