我有一个使用大量AJAX的ASP.NET MVC页面。在最基本的层面上,它包含一个问题列表,每个问题都有一个答案列表。我的观点模型(为了这个问题而大大简化):
查看模型:
public class QuestionViewModel
{
....
public string QuestionText { get; set; }
public List<AnswerViewModel> AnswerList { get; set; }
public bool EditMode { get; set; }
....
}
public class AnswerViewModel
{
....
public string Answer { get; set; }
....
}
_View.cshtml:
@model QuestionViewModel
@if(Model.EditMode)
{
@Html.EditorFor(x => x)
}
else
{
...
}
QuestionViewModel.cshtml(编辑模板):
@model Project.Models.QuestionViewModel
....
@Html.EditorFor(x => x.AnswerList)
....
AnswerViewModel.cshtml(编辑模板):
@model KSUAdvising.Models.AnswerViewModel
....
@Html.TextBoxFor(x => x.Answer)
....
^^^这个EditorFor调用使我的答案列表很好(连同适当的索引,因此模型绑定器将适当地绑定回列表。即:
<input id="AnswerList_0__Answer" name="AnswerList[0].Answer" type="text" value="Yes">
<input id="AnswerList_1__Answer" name="AnswerList[1].Answer" type="text" value="No">
但是,在客户端,我需要在用户单击按钮时将项添加到此列表中。这需要在客户端进行,因此在用户保存问题之前不会对数据库进行任何更改。
我看到了解决这个问题的方向:
这似乎是一种常见的情况,但我很难找到一个好的解决方案。这种情况的推荐方法是什么?
答案 0 :(得分:1)
我投票支持选项2。
呈现隐藏的HTML项目模板。然后在客户端按钮上单击,克隆模板并修改索引。
在cshtml页面中,在foreach之后,为模板添加一个新的隐藏div。给它一个索引占位符(我使用_ x0x_)。创建一个新的空项目,然后以与foreach中相同的方式呈现它。 (您也可以将项目呈现为部分视图,然后在foreach内外调用它。)
以下是示例cshtml页面:
@foreach (var role in roles)
{
int roleIndex = roles.IndexOf(role);
string rolePrefix = "CasePartyRoles[" + roleIndex + "].";
<div id="CasePartyRoleIndex_@roleIndex" class="row brdr-bttm mrgn-bttm-sm">
<div class="col-md-10 mrgn-bttm-sm">
@Html.Hidden(rolePrefix + "SequenceNo", role.SequenceNo)
@Html.Hidden(rolePrefix + "RowVersion", role.RowVersion)
@Html.DropDownListFormGroupFor(modelItem => role.PartyRoleCode, (SelectList)ViewBag.PartyRoleSelectList, null, "col-md-3", "col-md-9", null, role.PartyRoleCode, rolePrefix + "PartyRoleCode")
@Html.DropDownListFormGroupFor(modelItem => role.PartyStatusCode, (SelectList)ViewBag.PartyStatusSelectList, null, "col-md-3", "col-md-9", null, role.PartyStatusCode, rolePrefix + "PartyStatusCode")
@Html.EditorFormGroupFor(modelItem => role.SubFileNo, "col-md-3", "col-md-9", null, null, rolePrefix + "SubFileNo")
@Html.EditorFormGroupFor(modelItem => role.PartyRank, "col-md-3", "col-md-9", null, null, rolePrefix + "PartyRank")
</div>
</div>
}
<div id="CasePartyRoleTemplate" class="hidden">
@*Template for new Role*@
@{
var newRole = new CasePartyRole();
string newRolePrefix = "CasePartyRoles[_x0x_].";
}
<div id="CasePartyRoleIndex__x0x_" class="row brdr-bttm mrgn-bttm-sm">
<div class="col-md-10 mrgn-bttm-sm">
@Html.Hidden(newRolePrefix + "SequenceNo", newRole.SequenceNo)
@Html.Hidden(newRolePrefix + "RowVersion", newRole.RowVersion)
@Html.DropDownListFormGroupFor(modelItem => newRole.PartyRoleCode, (SelectList)ViewBag.PartyRoleSelectList, null, "col-md-3", "col-md-9", null, newRole.PartyRoleCode, newRolePrefix + "PartyRoleCode")
@Html.DropDownListFormGroupFor(modelItem => newRole.PartyStatusCode, (SelectList)ViewBag.PartyStatusSelectList, null, "col-md-3", "col-md-9", null, newRole.PartyStatusCode, newRolePrefix + "PartyStatusCode")
@Html.EditorFormGroupFor(modelItem => newRole.SubFileNo, "col-md-3", "col-md-9", null, null, newRolePrefix + "SubFileNo")
@Html.EditorFormGroupFor(modelItem => newRole.PartyRank, "col-md-3", "col-md-9", null, null, newRolePrefix + "PartyRank")
</div>
</div>
</div>
这是一个基于模板添加项目的小jQuery函数:
function createItemFromTemplate(templateId, indexNo, insertBeforeId) {
// Copy the template Element, replaces all the _x0x_ with the index no and add the new element
$(insertBeforeId).before($.parseHTML($(templateId).clone().prop('outerHTML').replace(/_x0x_/g, indexNo)));
}
答案 1 :(得分:0)
这取决于...为了表现,我不会选择第一个选项。通过Ajax加载新项目的这种轻微延迟可能很烦人。
就个人而言,大多数时候我只会在客户端完全构建一个HTML元素。我知道这会使维护变得复杂,因为您必须记住在您对模型集合进行更改时更改客户端逻辑,但这是快速而直接的。
还有一个想法如何改善你的第二个选择。基本上,你不需要有一个真实的对象来构建它。
@Html.TextBoxFor(model => model.Items[int.MaxValue], new { style= "display:none" })
提交的输入
<input name="Items[2147483647]" id="Items_2147483647_" style="display: none;" type="text" value="">
请注意,在我的情况下,Items属性为null,但是如果你只是想构建一个模板,那么无关紧要xxxFor html helpers只是使用表达式来构建html。此外,在使用真实索引克隆模板时,替换int.MaxValue非常容易。使用int.MaxValue作为占位符是安全的,非常简单的是你的页面上会有很多项目。
希望它有所帮助!