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

时间:2017-10-20 17:11:49

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

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

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

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

这是我使用的剃刀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>

有一种简单的方法吗?我不想要硬编码。

2 个答案:

答案 0 :(得分:7)

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

现在,在EditorTemplates~/Views/YourControllerName下创建一个名为~/Views/Shared/的目录,并创建一个名为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>

标记具有用于添加新项目的锚标记。因此,当用户点击它时,我们需要添加一个新的输入元素,其名称属性值的格式为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属性,编辑器模板将负责使用正确的名称属性值呈现每个项目的输入元素。 / p>

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

答案 1 :(得分:-1)

首先,您必须拥有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类所在的文件夹。