ASP.NET MVC;使用EditorTemplates编辑集合,这是动态字段创建的最佳方式

时间:2013-05-02 00:41:35

标签: asp.net-mvc mvc-editor-templates

我是ASP.NET MVC的新手,如果这比看起来更容易,请道歉。我一直在谷歌搜索,我有一个像这样:

public class Search : IAuditable
{
    [Key]
    public int SearchID { get; set; }
    public int UserID { get; set; }

    ...

    public ICollection<SearchTerm> SearchTerms { get; set; }   
}

Create.cshtml 中,我有以下

<div class="editor-label">
    @Html.LabelFor(model => model.Search.SearchTerms)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Search.SearchTerms, "SearchTerm")
    @Html.ValidationMessageFor(model => model.Search.SearchTerms)
</div>

SearchTerm EditorTemplate 是一个简单的表单,如下所示:

@model Core.Search.Parameters.SearchTerm

@Html.HiddenFor(n => n.SearchTermID)
<div class="editor-label">
    @Html.LabelFor(n => n.Text, "Term")
</div>
<div class="editor-field">
    @Html.EditorFor(n => n.Text)
    @Html.ValidationMessageFor(n => n.Text)
</div>

似乎工作正常,我在创建时看到一个文本框(当默认模型为空时)。但是,我想要做的是能够使用添加按钮添加/删除SearchTerms,以便用户可以在创建<上添加任意数量的术语 / em>的。这是以某种方式建造的吗?是否有一个与此配对良好的javascript框架,它将生成相应的html名称,所以我不必手动执行此操作?鉴于我是MVC的新手,我是否正确地接近这个?

谢谢!

3 个答案:

答案 0 :(得分:6)

在这种情况下,我更喜欢使用PartialView。

您应该创建一个ActionResult,它会为您的项目返回PartialView。当您单击“添加”按钮时,您应该向此ActionResult发送ajax请求。

public ActionResult GetTermItem()
{
    return PartialView("_SearchTerm", new SearchTerm());
}

您的PartialView应如下所示:

@model Core.Search.Parameters.SearchTerm
@{ ViewContext.FormContext = new FormContext(); }
@using (Html.BeginCollectionItem("SearchTerms"))
{
    <div class="search-term-item">            
       @Html.HiddenFor(n => n.SearchTermID)
       <div class="editor-label">
          @Html.LabelFor(n => n.Text, "Term")
       </div>
       <div class="editor-field">
          @Html.EditorFor(n => n.Text)
          @Html.ValidationMessageFor(n => n.Text)
       </div>

       <a href="javascript:void(0);" class="remove-search-item" title="Remove">Remove</a>
    </div>
}

您的主页:

<div class="editor-label">
    @Html.LabelFor(model => model.Search.SearchTerms)
</div>
<div id="search-terms-container" class="editor-field">
    @if (Model.SearchTerms != null && Model.SearchTerms.Any())
    {
        foreach (var item in Model.SearchTerms)
        {
             @Html.Partial("_SearchTerm", item)
        }
    }
</div>
<a href="javascript:void(0);" id="add-search-item">Add</a>

和你的JavaScript(jQuery)部分:

$(document).on('click', '#add-search-term', function () {
    $.ajax({
        url: '@Url.Action("GetTermItem")',
        cache: false,
        success: function (data) {
            var cl = $('#search-terms-container');
            cl.append(data);
            var terms = cl.find('.search-term-item');
            terms.last().hide().show('blind');
        }
    });
    return false;
});

$(document).on('click', '.remove-search-term', function () {
    $(this).closest('.search-term-item').hide('blind', function () { $(this).remove(); });
    var cl = $('#search-terms-container');
    var terms= cl.find('.search-term-item');
    return false;
});

答案 1 :(得分:0)

如果你想真正模拟绑定,你需要使用Ajax或JQuery / javavscript。在添加时,您可以执行:

$(".editor-field").load(url, function(){ // anonymous return call });

或者仅仅通过javascript添加搜索词可能更简单。只要元素的名称匹配,MVC就会将数据作为IEnumerable发送到服务器。因此,如果您的模型包含SearchTerms,则EditorFor将使用索引追加每个项目名称,即SearchTerms [0] .Name。这样,所有映射都基本上在幕后发生,但是,可以克隆您的术语并修改

$("#YourClone").attr("name", "SearchTerms" + index);

答案 2 :(得分:0)

我在用户表单中用地址做了类似的事情,添加了点击+按钮的地址,这就是代码

查看

$(document).on("click", "#addRowInd", function (ev) {
    ev.preventDefault();
    var index = (($("input[name^='Indirizzi']").filter(":hidden").length));
    var input = "<table>";
    input += "<tr>";
    input += "<td><label for=\"Indirizzi_"+index+"__Descrizione\">Descrizione</label></td>";
    input += "<td><input id=\"Indirizzi_" + index + "__Descrizione\" type=\"text\" name=\"Indirizzi[" + index + "].Descrizione\"></td>";
    input += "</tr>";
    input += "<tr>";
    input += "<td><label for=\"Indirizzi_" + index + "__Citta\">Citta</label></td>";
    input += "<td><input id=\"Indirizzi_" + index + "__Citta\" type=\"text\" name=\"Indirizzi[" + index + "].Citta\"></td>";
    input += "</tr>";
    input += "<tr>";
    input += "<td><label for=\"Indirizzi_" + index + "__Provincia\">Provincia</label></td>";
    input += "<td><input id=\"Indirizzi_" + index + "__Provincia\" type=\"text\" name=\"Indirizzi[" + index + "].Provincia\"></td>";
    input += "</tr>";
    input += "<tr>";
    input += "<td><label for=\"Indirizzi_" + index + "__Cap\">Cap</label></td>";
    input += "<td><input id=\"Indirizzi_" + index + "__Cap\" type=\"text\" name=\"Indirizzi[" + index + "].Cap\"></td>";
    input += "</tr>";
    input += "<tr>";
    input += "<td><label for=\"Indirizzi_" + index + "__Via\">Via</label></td>";
    input += "<td><input id=\"Indirizzi_" + index + "__Via\" type=\"text\" name=\"Indirizzi[" + index + "].Via\"></td>";
    input += "</tr>";
    input += "</table>";
    $('#tabella').find('tr.indirizzo:last').after("<tr class=\"indirizzo\"><td>Indirizzo <img src=\"/Content/layout/ico-cancella-8.png\" class=\"cancInd\" id=\"" + index + "\" /></td><td>" + input + "</td></tr>");
});

[...]

<tr class="indirizzo">
    <td>@Html.LabelFor(m => Model.Indirizzi) <input id="addRowInd" type="button" /></td>
    <td>@Html.EditorFor(m => m.Indirizzi[0])</td>
</tr> 

模型

public class ContattoModel
{
    [...]
    [Display(Name = "Indirizzo")]
    public List<Indirizzi> Indirizzi { get; set; }
    [...]
}

和控制器

public ActionResult ContattiForm([ModelBinder(typeof(ContattiBinder))]ContattoModel model){

 [...]
}

所以在我的模特中.Indirizzi我得到了我通过+按钮添加的所有地址