创建在运行时增长的动态表单

con*_*rio 3 forms asp.net-mvc asp.net-core

我在MVC应用程序中的asp.net核心工作.我正在使用脚手架功能,根据模型创建视图和控制器.以下是我正在使用的模型:

class ShoppingList
{
    public int ShoppingListId { get; set; }
    public string Name { get; set; }
    public List<string> ListItems { get; set; }            
}
Run Code Online (Sandbox Code Playgroud)

通过视图向用户显示的表单仅显示名称的字段.我希望表单能够显示列表项的字段,然后如果用户想要添加另一个列表项,他们可以点击按钮添加另一个字段来执行此操作.他们在运行时决定他们想要添加多少购物清单项目.

这是我正在使用的剃刀cshtml表单:

<form asp-action="Create">
     <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
           <label asp-for="Name" class="control-label"></label>
           <input asp-for="Name" class="form-control" />
           <span asp-validation-for="Name" class="text-danger"></span>
        </div>
     <div class="form-group">
     <input type="submit" value="Create" class="btn btn-default" />
     </div>
</form>
Run Code Online (Sandbox Code Playgroud)

是否有捷径可寻?我不想硬编码.

Shy*_*yju 9

如果要允许用户在客户端添加新的表单元素,则需要使用javascript来更新要添加的新元素的DOM.要列出现有项目,您可以使用编辑器模板.混合这两个将给你一个动态的形式.以下是基本实现.

要使用编辑器模板,我们需要为属性类型创建一个编辑器模板.对于string更像普通类型的类型,我不会这样做.我会创建一个自定义类来表示列表项.

public class Item
{
    public string Name { set; get; }
}
public class ShoppingList
{
    public int ShoppingListId { get; set; }
    public string Name { get; set; }
    public List<Item> ListItems { get; set; }

    public ShoppingList()
    {
        this.ListItems=new List<Item>();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,创建一个名为EditorTemplatesunder ~/Views/YourControllerName或的目录,~/Views/Shared/并创建一个名为的视图Item.cshtml,其中包含以下代码

@model  YourNameSpaceHere.Item
<input type="text" asp-for="Name" class="items" />
Run Code Online (Sandbox Code Playgroud)

现在在您的GET控制器中,创建ShoppingList的对象并发送到视图.

public IActionResult ShoppingList()
{
    var vm = new ShoppingList() {  };
    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)

现在在主视图中,您所要做的就是调用EditorFor方法

@model YourNamespace.ShoppingList
<form asp-action="ShoppingList" method="post">
    <input asp-for="Name" class="form-control" />
    <div class="form-group" id="item-list">
        <a href="#" id="add">Add</a>
        @Html.EditorFor(f => f.ListItems)
    </div>
    <input type="submit" value="Create" class="btn btn-default" />
</form>
Run Code Online (Sandbox Code Playgroud)

标记具有用于添加新项目的锚标记.因此,当用户点击它时,我们需要添加一个带有name属性值的新输入元素ListItems[indexValue].Name

$(function () {

   $("#add").click(function (e) {
       e.preventDefault();
       var i = $(".items").length;
       var n = '<input type="text" class="items" name="ListItems[' + i + '].Name" />';
       $("#item-list").append(n);
   });

});
Run Code Online (Sandbox Code Playgroud)

因此,当用户单击它时,会向DOM添加一个具有正确名称的新输入元素,当您单击提交按钮时,模型绑定将正常工作,因为我们具有输入的正确名称属性值.

[HttpPost]
public IActionResult ShoppingList(ShoppingList model)
{
    //check model.ListItems
    // to do : return something
}
Run Code Online (Sandbox Code Playgroud)

如果要预加载某些现有项目(用于编辑屏幕等),您只需加载ListItems属性,编辑器模板将负责使用正确的name属性值呈现每个项目的输入元素.

public IActionResult ShoppingList()
{
    var vm = new ShoppingList();
    vm.ListItems = new List<Item>() { new Item { Name = "apple" } }
    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)