【问题标题】:How to add an item to a list in a ViewModel using Razor and .NET Core?如何使用 Razor 和 .NET Core 将项目添加到 ViewModel 中的列表?
【发布时间】:2016-07-18 23:02:34
【问题描述】:

这就是我的情况。

假设我有一个名为 TheView.cshtml. TheView.cshtml 的视图有一个名为 TheViewModel.cs 的 ViewModel。在TheViewModel.cs 中,有一个名为TheObjectList 的对象(TheObject) 的列表。

我有一个TheObject 的编辑器模板,名为TheObject.cshtml。使用这个编辑器模板,我可以简单地显示TheObjectList@Html.EditorFor(model => model.TheObjectList) 中的所有项目。

但是,现在我想动态地将对象添加到此列表中。我有一个 AJAX 函数,它调用一个简单的局部视图来给用户一个空白行来添加一个新的“TheObject”,但是,我动态添加的任何新的TheObject 都不被视为原始TheObjectList 的一部分。

这是因为原始 TheObjectList 中的每个项目都是根据其在原始列表中的索引创建的,而每个新的动态 TheObject 都是在没有前缀的情况下创建的,因此 Razor 不会将其视为列表。

有没有办法解决这个问题?

TheView.cshtml

@model Models.ViewModels.TheViewModel

<table id="Table">
    <tbody>
        @Html.EditorFor(m => m.TheObjectList);
    </tbody>
</table>

<button id="AddObject" type="button" class="btn btn-primary">Add Object</button>

TheViewModel.cs

public class TheViewModel
{
    public List<TheObject> TheObjectList { get; set; }
}

AddObject 控制器方法

public IActionResult AddObject()
{
   return PartialView("_EmptyRow", new TheObject());
}

AJAX方法添加对象

$('#AddObject').click(function () {
    $.ajax({
        url: 'AddObject',
        cache: false,
        success: function (data) {
            $('#Table > tbody').append(data);
        },
        error: function (a, b, c) {
            alert(a + " " + b + " " + c);
        }
     });
});

【问题讨论】:

  • 如何将 AddObject 的结果添加到现有表单中?
  • @Shyju 我已经用代码更新了 OP。这是一种 AJAX 方法,将空行添加为表格行
  • 参考答案herehere
  • @StephenMuecke 不幸的是,DNX Core 不支持“BeginCollectionItem”:(否则这会为我节省大量时间和头痛
  • 然后使用客户端模板选项(无论如何性能要好得多)

标签: c# asp.net-mvc asp.net-mvc-4 razor viewmodel


【解决方案1】:

您基本上需要生成/返回标记,该标记看起来与编辑器模板为您的表单字段生成的标记相同,但元素 index 除外。您需要从客户端传递索引,该索引将成为表单字段名称的一部分。

假设您的编辑器模板如下所示,并且您的 TheObject 具有 GroupName 属性

@model TheObject
<div>
    @Html.HiddenFor(x => x.GroupName)
    @Html.TextBoxFor(s=>s.GroupName,new {@class="thingRow"})
</div>

现在,当您使用当前代码渲染页面时,编辑器模板将生成像这样的输入字段

<input class="thingRow" id="TheObjectList_0__GroupName" 
                           name="TheObjectList[0].GroupName" type="text" value="Something">

其中0 将替换为您的TheObjectList 集合中项目的索引。

现在假设你已经有 5 个项目在集合中,所以当用户点击添加按钮时,你想要生成像上面一样的标记,除了 0 将被替换为 5(第六个项目 em>)。因此,让我们更新 ajax 调用以包含当前的项目数。

$('#AddObject').click(function () {
    var i = $(".thingRow").length;
    $.ajax({
        url: 'AddObject?index=' + i,
        success: function (data) {
            $('#Table > tbody').append(data);
        },
        error: function (a, b, c) {
            console.log(a, b, c);
        }
    });
});

这意味着,我们需要在我们的操作方法中接受索引值。由于我们需要将此索引值从 action 方法传递到我们的视图以构建输入字段名称值,因此我在您的类中添加了一个属性,名为 Index

public ActionResult AddObject(int index)
{
    return PartialView("_EmptyRow", new TheObject { Index = index});
}

现在在您的 _EmptyRow 部分视图中,

@model TheObject
<input id="TheObjectList_@(Model.Index)__GroupName"class="thingRow" 
             name="TheObjectList[@(Model.Index)].GroupName"  type="text" value=""/>

现在,当您提交表单时,模型绑定将对这些动态添加的项目起作用,假设您的表格位于表单中。

@model TheViewModel
@using (Html.BeginForm())
{   
    <table id="Table">
        <tbody>
            @Html.EditorFor(m => m.TheObjectList);
        </tbody>
    </table>
    <button id="AddObject" type="button" class="btn btn-primary">Add Object</button>
    <button type="submit" class="btn btn-primary">Save</button>
}

【讨论】:

  • 天哪,如果我能给你送 12 包啤酒我会的。我整天都被困在这个问题上,你的答案是如此明显,我不敢相信我没有想到它。非常感谢 - 我希望我能给你更多的声誉。再次感谢!!
  • 嘿伙计还有一个问题 - 也许你可以在这里帮助我。添加效果很好,但假设我想从列表中删除。如果我从列表中间删除一个,那么它之后的所有其他项目也会被删除
  • 对于删除,您需要编写一些javascript,它会更新所有以下元素的索引......或者作为第二种选择:只需添加一个带deleted = true的隐藏输入元素,然后处理删除表单已提交
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2020-04-06
  • 2020-02-04
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多