问题描述
|
因此,去年我问了一个有关“添加项目”按钮的问题,该按钮将在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;
}
});
});
}
这可能与您的工作完全无关,但希望对您有所帮助。