【问题标题】:Create dynamic forms that grow at run time创建在运行时增长的动态表单
【发布时间】:2018-11-21 03:21:18
【问题描述】:

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

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

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

这是我正在使用的 razor 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>

有没有简单的方法来做到这一点?我不想硬编码一个数字。

【问题讨论】:

  • 使用 jQuery 向 DOM 添加输入元素。
  • 我遇到的问题是,当我提交表单时,新添加的元素不会随提交一起发送。 @Shyju
  • 只要我们的名称与模型绑定器正在查找的内容匹配,它就会执行此操作。分享您尝试过的代码
  • @JeremyConterio 如果您使用 Razor 视图,我会为您解答。
  • @Jared 我正在使用剃须刀页面。我将更新我的问题以显示我正在使用的表单。

标签: asp.net-mvc forms asp.net-core


【解决方案1】:

如果你想允许用户在客户端添加一个新的表单元素,你需要使用 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>();
    }
}

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

@model  YourNameSpaceHere.Item
<input type="text" asp-for="Name" class="items" />

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

public IActionResult ShoppingList()
{
    var vm = new ShoppingList() {  };
    return View(vm);
}

现在在主视图中,你所要做的就是调用 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>

标记具有用于添加新项目的锚标记。所以当用户点击它时,我们需要添加一个新的 input 元素,其 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);
   });

});

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

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

如果您想预加载一些现有项目(用于编辑屏幕等),您所要做的就是加载 ListItems 属性,编辑器模板将负责为每个项目呈现正确的名称属性值的输入元素。

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

【讨论】:

    【解决方案2】:

    首先,您必须拥有 ShoppingList 类的公共访问器。

    所以,public class ShoppingList

    接下来是您的视图需要进行以下更改。

    @model ShoppingList
    
    <h1>@Model.Name</h1>
    <h2>@Model.ShoppingListId</h2>
    foreach(var item in Model.ListItems)
    {
        <h3>@item</h3>
    }
    

    所以,上面的代码大致就是你要找的。 在 Razor 中,您可以使用视图顶部的 @model 访问模型变量。但是您需要注意的一件事是,如果您的模型位于子文件夹中,则需要在其中添加点。

    这是一个示例:@model BethanysPieShop.Models.ShoppingCart

    这里 BethanysPieShop 是我的项目名称,Models 是我的 ShoppingCart 类所在的文件夹。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-22
      • 1970-01-01
      • 2010-11-14
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多