I'm working on an MVC web application and have a requirement to have a variable length list of items. User should be able to add / edit and delete rows with a save doing a batch update on all rows.
我正在开发一个MVC Web应用程序,并且要求有一个可变长度的项目列表。用户应该能够添加/编辑和删除行,并在所有行上执行批量更新。
I started off working from two blog posts which have pretty much covered most of the work so all credit to Steve Sanderson.
我从两篇博文开始工作,这些博文几乎涵盖了大部分工作,所以全部归功于史蒂夫桑德森。
Editing a variable-length list of items in ASP.NET MVC
在ASP.NET MVC中编辑可变长度的项列表
I have my view as follows
我的观点如下
<% using (Html.BeginForm()) { %>
<div id="placeholder">
<% for (int i = 0; i < Model.Count(); i++)
{
ViewData["index"] = i;
Html.RenderPartial("ProfileItemLine", Model.ElementAt(i), new ViewDataDictionary(ViewData) {
{"prefix", "items"}
});
}
%>
</div>
<div id="addProfileItem">
<a href="" id="addItem">Add another item</a>
</div>
<input type="submit" value="Save changes" />
<% } %>
And use jQuery to handle additions and deletes
并使用jQuery来处理添加和删除
$(document).ready(function() {
var nextIndex = <%=ViewData.Model.Count()%>;
setRemoveLinks();
$('#addItem').click(function() {
var action = '/Profile/BlankItemLine?index=' + nextIndex;
$.get(action, 'html', function(lineItemHtml) {
$('#placeholder').append(lineItemHtml);
setRemoveLinks();
});
nextIndex++;
return false;
});
});
function setRemoveLinks() {
$('a.removeItem').click(function() {
$(this).parent('div').remove();
return false;
});
}
The ProfileItemLine ViewUserControl is as follows minus formatting and plain text
ProfileItemLine ViewUserControl如下所示减去格式和纯文本
<div>
<% var fieldPrefix = string.Format("{0}[{1}].", ViewData["prefix"], ViewData.Model.Sequence); %>
<%= Html.Hidden(fieldPrefix + "ProfileItemId", ViewData.Model.ProfileItemId)%>
<%= Html.TextBox(fieldPrefix + "Title", ViewData.Model.Title, new { size = "30"})%>
<%= Html.CheckBox(fieldPrefix + "IsHighlighted", ViewData.Model.IsHighlighted)%>
<a href="" class="removeItem">Delete</a></div>
So far so good, the list binds correctly to the model and as long as I only add items it works too.
到目前为止一切顺利,该列表正确地绑定到模型,只要我只添加它也适用的项目。
The problem is related to deletes. The delete works and removes the correct row but I lose all bindings on form submit. In Steve's post he mentions that the RC has changed the way the model binding works and it requires all indexes to be in an unbroken ascending sequence.
问题与删除有关。删除工作并删除正确的行但我丢失了表单提交上的所有绑定。在Steve的帖子中,他提到RC已经改变了模型绑定的工作方式,并且它要求所有索引都处于不间断的升序中。
Steve listed some code to get working which involved reordering the list on form submit but it throws an exception at the "var controls =" line with method not supported.
史蒂夫列出了一些代码来实现工作,其中涉及在表单提交上重新排序列表,但它在“var controls =”行引发异常,方法不受支持。
$(function() {
$("form").submit(function() {
// Normalize the sequence before submitting the form
ensureControlGroupsInNumericalOrder("#placeholder div", "items");
});});
function ensureControlGroupsInNumericalOrder(groupSelector, controlNamePrefix) {
var groups = $(groupSelector);
var nameToEndOfIndexRegex = new RegExp(controlNamePrefix + "\\[\\d+");
for (var seq = 0; seq < groups.length; seq++) {
var controls = $("*[name~=" + controlNamePrefix + "\[]", groups[seq]);
for (var c = 0; c < controls.length; c++)
controls[c].name = controls[c].name.replace(nameToEndOfIndexRegex, controlNamePrefix + "[" + seq);
}}
Example of html output after two deletes of indexes 1 and 2
两次删除索引1和2后的html输出示例
<div id="placeholder">
<div>
<input id="items[0]_ProfileItemId" name="items[0].ProfileItemId" type="hidden" value="0fd3a3f5-907e-4eb1-8f69-26e3840e5e12" />
<input id="items[0]_Title" name="items[0].Title" size="30" type="text" value="Number 1" />
<input id="items[0]_IsHighlighted" name="items[0].IsHighlighted" type="checkbox" value="true" />
<input name="items[0].IsHighlighted" type="hidden" value="false" />
<a href="" class="removeItem">Delete</a>
</div>
<div>
<input id="items[3]_ProfileItemId" name="items[3].ProfileItemId" type="hidden" value="0fa1a3f5-907e-4eb1-8f69-26e3840e5e12" />
<input id="items[3]_Title" name="items[3].Title" size="30" type="text" value="Number 3" />
<input id="items[3]_IsHighlighted" name="items[3].IsHighlighted" type="checkbox" value="true" />
<input name="items[3].IsHighlighted" type="hidden" value="false" />
<a href="" class="removeItem">Delete</a>
</div>
</div>
I model bind to an IEnumerable on form submit, in this example I would only get the first item back and not the second due to it being items[3] rather than items1.
我模型绑定到表单提交上的IEnumerable,在这个例子中,我只返回第一个项目而不是第二个项目,因为它是项目[3]而不是items1。
public ActionResult EditItems(Guid id, IEnumerable<ProfileItem> items)
{
if (ModelState.IsValid)
{
// Save items
}
if (ModelState.IsValid)
return RedirectToAction("Index");
else
return View(items);
}
I'm still cutting my teeth on jQuery and regular expressions so I wonder if anybody can point me to a solution.
我仍然在研究jQuery和正则表达式,所以我想知道是否有人可以指出我的解决方案。
Thanks in advance
提前致谢
1 个解决方案
#1
1
Why would you need al the individual element info ?
为什么你需要单独的元素信息?
Wouldn't it be wiser to use
使用它不是更明智的
<div id="div1">
For deleting ?
要删除吗?
<a rel="1" id="item + item id (not per se 1 )" class="delete">delete</a>
So you can use
所以你可以使用
$('.delete').bind('click',function(){
$('#div' + $(this).attr('rel') ).remove();
// plus delete call to db ?
});
That's what I always do :)
这就是我经常做的:)
You can have the numbers of the div and rel made up in your html creation loop, so the order is always correct.
您可以在html创建循环中创建div和rel的编号,因此顺序始终正确。
#1
1
Why would you need al the individual element info ?
为什么你需要单独的元素信息?
Wouldn't it be wiser to use
使用它不是更明智的
<div id="div1">
For deleting ?
要删除吗?
<a rel="1" id="item + item id (not per se 1 )" class="delete">delete</a>
So you can use
所以你可以使用
$('.delete').bind('click',function(){
$('#div' + $(this).attr('rel') ).remove();
// plus delete call to db ?
});
That's what I always do :)
这就是我经常做的:)
You can have the numbers of the div and rel made up in your html creation loop, so the order is always correct.
您可以在html创建循环中创建div和rel的编号,因此顺序始终正确。