【问题标题】:Bind dynamically created element to complex mvc model in view将动态创建的元素绑定到视图中的复杂 mvc 模型
【发布时间】:2013-11-21 22:16:26
【问题描述】:

我的应用程序中有一个非常大的表单,在我的模型中有很多不同的输入和很多列表。所以我会尝试添加/删除列表而不将完整的模型发送到服务器。

我现在尝试了几种方法,但我找不到干净的方法。你可以把我的模型想象成这样:

public class EditSomething
{
    public string name { get; set;}

    public List<something> somethingList { get; set;}

    // a lot other fields...

    public EditSomething(EditSomethingFromDatabase editSomethingFromDatabase)
    {
        name = editSomethingFromDatabase.Name;
        somethingList = new List<SomethingModel>();
        foreach(var something in editSomethingFromDatabase.Something)  
        {
            somethingList.Add(new SomethingModel(editSomethingFromDatabase.Something));
        }
    }
}

另一个模型看起来很相似,但没有列表。

在视图中我有一个模型表:

    <h2>Something</h2> 
    <div id="SomethingDiv">
        <table id="SomethingTable">
            <thead>
                <tr>
                    <th>@Html.Label("SomethingName")</th>
                    <th>@Html.Label("SomethingID")</th>
                                                <th></th>
                </tr>
            </thead>
            <tbody id="SomethingTableBody">

                @Html.EditorFor(x => x.somethingList)

            </tbody>
        </table>
        <p>
            <input type="button" name="addSomething" value="Add Something" id="AddSomething">
        </p>
    </div>

addSomething 的 jquery 是:

  $('#AddSomething').click(function () {
        $.ajax({
            url: '@Url.Action("AddSomething", "SomethingModels")',
            data: { tableSize: $('#SomethingTable tr').length },
            cache: false,
            success: function (html) { $('#SomethingTable tr:last').after(html); }
        });

控制器方法AddSomething是:

public ActionResult AddSomething (int tableSize)
{
    SomethingModel something= new SomethingModel(null, (-2) * (tableSize + 1));
    return PartialView(""~/Views/EditorTemplates/EditSomethingModel.cshtml"", something);
}

至少我在 EditorTemplates 中有一个编辑器模板,用于 editorfor 和 partialview。这有我想发送到服务器的重要信息:

@model SomethingModel
<tr>@TextBoxFor(m=>m.SomethingName)<td>

@TextBoxFor(m=>m.SomethingID)

所以现在的问题是,第一个视图的提交只将SomethingModel 发布到打开视图时已经存在的服务器,但AddMutation 方法中的新SomethingModel 不在帖子中。有人想解决这个问题吗?

编辑:更改了编辑器模板的路径,因此我只需要EditorForPartialView 的一个视图。

Edit2:为了解决主要问题,我创建了如下视图并将其用作局部视图。现在数据已正确发送到服务器。只有客户端的验证仍然不起作用:

@model SomethingModel
    <tr>@TextBoxFor(m=>m.SomethingName, new{Name="somethingList["+ViewBag.ListId+"].SomethingName")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingName" data-valmsg-replace="true"></span><td>
<tr>@TextBoxFor(m=>m.SomethingID, new{Name="somethingList["+ViewBag.ListId+"].SomethingID")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingID" data-valmsg-replace="true"></span><td>
</tr>

AddSomething 方法中,我添加了ViewBag.ListId 以及列表中下一个元素的ID。

【问题讨论】:

  • 我已经更改了我的答案,您需要进行更改以在 ajax 回调后获得不显眼的验证以使用您的新字段。
  • 是的,见。但是您需要从要提交的表单中删除所有验证。这将起作用:var table = $('#SomethingForm').removeData("validator").removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse(table); 非常感谢

标签: c# asp.net-mvc jquery asp.net-mvc-4


【解决方案1】:

这似乎是一个足够合理的方法,但你没有显示你的 EditorTemplate,所以我假设它是这样的:

@model List<something>

@for(int i = 0; i < Model.Count; i++)
{
   <tr>
     <td>@Html.DisplayFor(m => m[i].Id) @Html.HiddenFor(m => m[i].Id)</td>
     <td>@Html.EditorFor(m => m[i].Name)</td>
   </tr>
}

您的 ajax 方法应该返回一行的 HTML - 这很重要...表单字段需要在表中最后一个字段上方命名为 1。

因此,当您查看表格的渲染源时(在添加任何新字段之前,它可能看起来像:

...
<tbody>
   <tr>
     <td>1 <input type="hidden" name="something[0].Id" value="1"/></td>
     <td><input type="text" name="something[0].Name" value="somename" /></td>
   </tr>
</tbody>

您需要确保 ajax 方法为您的新行返回的 html 是:

   <tr>
     <td>2 <input type="hidden" name="something[1].Id" value="2"/></td>
     <td><input type="text" name="something[1].Name" value="somenewname" /></td>
   </tr>

即。括号内的数字是某物中项目的下一个索引。如果索引中存在间隙(或它们重叠),则不会解析新项目。

编辑 - 让客户端验证适用于新字段改变你的 jquery ajax 成功回调如下:

$('#AddSomething').click(function () {
    $.ajax({
        url: '@Url.Action("AddSomething", "SomethingModels")',
        data: { tableSize: $('#SomethingTable tr').length },
        cache: false,
        success: function (html) { 
            $('#SomethingTable tr:last').after(html);
            $.validator.unobtrusive.parse('#SomethingTable');
        }
    });

【讨论】:

  • 我更改了问题中的代码。最后一个代码示例是编辑器模板。我使用EditorFor 来显示somethingList 中的每个元素。 mvc 助手会自动为列表中的每个项目创建一个视图,因此您不需要使用循环。我的 ajax 方法也返回了一行的 HTML,但是你的权利,它不使用列表中的编号。而不是&lt;td&gt;&lt;input type="text" name="something[0].Name" value="somename" /&gt;&lt;/td&gt;,我只将它创建为&lt;td&gt;&lt;input type="text" name="Name" value="somename" /&gt;&lt;/td&gt;。所以谢谢你,我会检查我如何改变这个。
  • @James 如果您在索引上有空白,可以说因为您有一个减号按钮来删除动态 html,我该如何解析整个集合?
  • @Zinov 您需要一些 javascript 来重新索引所有字段,而不是删除字段。您不能在客户端字段索引中留下空白,否则它们将不会在回发时被解析。例如&lt;input type='button' value='Remove' onClick='removeRow(0)' /&gt;,然后定义一个删除行的javascript函数,并遍历具有更高索引的行集合 - 用[rowindex -1]替换所有[rowindex]实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2023-03-06
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多