用于绑定到集合的表单的“添加项目” JavaScript按钮-MVC3中的情况是否更好?

问题描述

| 因此,去年我问了一个有关“添加项目”按钮的问题,该按钮将在JavaScript表单中生成一个新行,可以返回到MVC POST操作处理程序。 例如,如果我生成这样的表单:
@for(int i = Model.Notes.Count - 1; i >= 0; i--)
{
    <tr>
        <td>@Html.HiddenFor(m => m.Notes[i].Id,new Dictionary<string,object> { { \"data-index\",i } } )
        @Html.TextBoxFor(m => m.Notes[i].Timestamp,new { @class = \"datepicker\" })</td>
        <td>@Html.DropDownListFor(m => m.Notes[i].PersonId,new SelectList(Model.People,\"Id\",\"Name\"))</td>
        <td>@Html.EditorFor(m => m.Notes[i].Amount)</td>
        <td>@Html.EditorFor(m => m.Notes[i].Comment)</td>
    </tr>
}
它为单行生成的HTML:
<tr>
                <td><input data-index=\"2\" data-val=\"true\" data-val-number=\"The field Id must be a number.\" data-val-required=\"The Id field is required.\" id=\"Notes_2__Id\" name=\"Notes[2].Id\" type=\"hidden\" value=\"16192\">
                <input class=\"datepicker hasDatepicker valid\" data-val=\"true\" data-val-required=\"The Timestamp field is required.\" id=\"Notes_2__Timestamp\" name=\"Notes[2].Timestamp\" type=\"text\" value=\"11/04/2011 2:11:21 PM\"></td>
                <td><select id=\"Notes_2__PersonId\" name=\"Notes[2].PersonId\">
<option value=\"8367\">Rei</option>
<option value=\"8668\">Ray</option>
<option value=\"8883\">Roy</option>
<option value=\"8814\">Rob</option>
<option value=\"8886\">Ron</option>
</select></td>
                <td><input class=\"text-Box single-line\" data-val=\"true\" data-val-number=\"The field Amount must be a number.\" data-val-required=\"The Amount field is required.\" id=\"Notes_2__Amount\" name=\"Notes[2].Amount\" type=\"text\" value=\"0.00\"></td>
                <td><input class=\"text-Box single-line\" id=\"Notes_2__Comment\" name=\"Notes[2].Comment\" type=\"text\" value=\"Some comment\"></td>
            </tr>
如果要在MVC2中添加项目,则必须编写一些非常干燥的JavaScript代码来确定最新项目的索引,生成所有
tr
td
input
HTML并设置属性以匹配。 这不仅非常重要,而且如果我在cshtml中进行了一些更改,我还必须非常小心以确保所有JavaScript都匹配。这是一个非常讨厌的代码重复。 在MVC3中还有更好的方法吗? 提前致谢, 丽     

解决方法

这是一篇博客文章,说明即使在MVC 2中这种情况也可能更好:-)而且,通过使用编辑器模板(MVC 2中也存在)甚至可以进一步改善这种情况,并且永远不要在视图中编写单个“ 5”循环。     ,我刚刚完成了类似的工作。我需要能够添加和删除行并使它们重新索引。我不确定您的问题是什么,但我认为这与此有关。 我的功能支持您不应该遇到的问题。我的字段最初是使用aaa。[n] .bbb的格式生成的,当它需要是aaa [n] .bbb时,但我确定您可以根据需要进行更改。 就我而言,我在AllEntries的末尾附加了一个局部视图,该局部视图有一个div现场,称为Entry。我希望这是有道理的。我使用默认索引0,然后在通过ajax加载了局部视图时,我只调用reindex函数,这样就无需跟踪当前索引,因此也使其可重用。 我的局部视图是这样生成的:
@model List<Address>
 @{ViewData.TemplateInfo.HtmlFieldPrefix = \"Addresses\";}

 <div class=\"editor-label\">
            @Html.LabelFor(model => model[0].BuildingName)
        </div>
        <div class=\"editor-field\">
            @Html.EditorFor(model => model[0].BuildingName)
            @Html.ValidationMessageFor(model => model[0].BuildingName)
        </div>

...etc
假设您有类似以下内容:
<div id=\"AllEntries\">

   <div id=\"Entry\">
     //Form inputs...
   </div>

   <div id=\"Entry\">
     //Form inputs...
   </div>

</div>

ReindexElements($(\'#Entry\',$(\'AllEntries\').children());
//Used to reindex input elements within a given set of divs
         //Supports changing from HtmlFieldPrefix and manual indexing
         //E.G Set = $(\'#Entry\' $(\'AllEntries\').children());
         function ReindexElements(Set) {
             $(Set).each(function (i,e) {
                 $(\'input\',this).each(function (ii,element) {
                     //Current element name
                     var FieldName = (element.name);

                     //aaaa.[n].bbbb
                     //This format is created when using ViewData.TemplateInfo.HtmlFieldPrefix = \"aaaa\"
                     //Incorrect for reading back into a model so it must be converted to the correct format described below
                     var IncorrectFormatRegex = \'((?:[a-z][a-z]+))(\\\\.)(\\\\[.*?\\\\])(\\\\.)((?:[a-z][a-z]+))\';

                     //aaaa[n].bbbb
                     //Correct format for being read back into an MVC model using TryUpdateModel()
                     var CorrectFormatRegex = \'((?:[a-z][a-z]+))(\\\\[.*?\\\\])(\\\\.)((?:[a-z][a-z]+))\';

                     var NewFieldName;

                     var RegexSplit = new RegExp(CorrectFormatRegex,[\"i\"]);
                     var RegexArray = RegexSplit.exec(FieldName);
                     if (RegexArray != null) {
                         //Field name is in correct format
                         NewFieldName = RegexArray[1] + \"[\" + i + \"].\" + RegexArray[4];

                     } else {

                         var RegexSplit = new RegExp(IncorrectFormatRegex,[\"i\"]);
                         var RegexArray = RegexSplit.exec(FieldName);
                         if (RegexArray != null) {
                             //Field name is incorrect format,lets fix that
                             NewFieldName = RegexArray[1] + \"[\" + i + \"].\" + RegexArray[5];
                         } else {
                             //Hasnt matched either regex ... Name must be incorrect,exit loop
                             return false;
                         }
                     }

                     if (FieldName != NewFieldName) {
                         //Rename element
                         $(element).attr(\'name\',NewFieldName);
                     } else {
                         //Attributes dont need renaming,exit loop
                         return false;
                     }
                 });
             });
         }
这可能与您的工作完全无关,但希望对您有所帮助。