I am new to MVC and JavaScript, so forgive my basic questions. I am writing a view that displays several rows of data and at the end of each row I am displaying a Remove button. When clicked, the button runs some JavaScript that removes the row using the .remove().
我是MVC和JavaScript的新手,所以请原谅我的基本问题。我正在编写一个视图,它显示了几行数据,在每一行的末尾,我将显示一个Remove按钮。单击时,该按钮运行一些JavaScript,使用.remove()删除行。
When I click the Remove button, the row is removed, but when I return to the controller, any rows below the row that was deleted is not transferred back to the controller and the count is one less then the row I deleted. For example if I have 6 rows and delete row 4, when I submit back to the controller, the count is 3 and rows 5 and 6 are missing. Not sure why. Below is my View and controller.
当我单击Remove按钮时,行被删除,但是当我返回到控制器时,被删除的行下面的任何行都不会转移回控制器,并且计数比我删除的行少1。例如,如果我有6行并删除第4行,当我提交回控制器时,计数为3,第5行和第6行缺失。不知道为什么。下面是我的视图和控制器。
Any help will be greatly appreciated.
如有任何帮助,我们将不胜感激。
View
视图
@using (Html.BeginForm("Edit", "Contacts", FormMethod.Post))
{
<table>
<tr>
<th><label>Last Name</label></th>
<th><label>First Name</label></th>
.... // more table headings
<th></th>
</tr>
@if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var i in Model)
{
<tr>
<td>
@Html.TextBoxFor(a => a[j].LASTNAME)
@Html.HiddenFor(a => a[j].DOB_NBR)
@Html.ValidationMessageFor(a => a[j].LASTNAME)
</td>
<td>
@Html.TextBoxFor(a => a[j].FIRSTNAME)
@Html.ValidationMessageFor(a => a[j].FIRSTNAME)
</td>
.... // more controls
<td><button type="button" id="btnDelete" class="deleteContact btn btn btn-danger btn-xs">Remove</button></td>
</tr>
j++;
}
}
</table>
<input type="button" class="add-button btn btn-default" name="add" value="Add" />
<input type="submit" name="submitAction" value="Submit" class="btn btn-primary" onclick="return confirm('Please double check all information before submitting. Submit Notification?')" />
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
$(document).on("click", ".deleteContact", function () {
$(this).closest("tr").remove();
});
</script>
Controller
控制器
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(string submitAction, List<ENTITY_CONTACTS> entity_Contacts)
{
// entity_Contacts is not bound with all items in the collection
}
1 个解决方案
#1
1
By default, the DefaultModelBinder
will only bind collections when the indexers are zero-based and consecutive. In your case, when you remove the 4th row, your indexers are 0, 1, 2, 4 and 5 so only the first 3 are bound. You can override this behavior by adding a hidden input for the indexer, which allows the DefaultModelBinder
to match up non-consecutive indexers.
默认情况下,DefaultModelBinder只在索引器为零和连续时绑定集合。在你的情况下,当你移除第4行时,你的索引器是0、1、2、4和5,所以只有前3个是绑定的。您可以通过为索引器添加隐藏的输入来覆盖此行为,这允许DefaultModelBinder匹配非连续索引器。
Change your loop to
改变你的循环
for (int i = 0; i < Model.Count; i++) // do not use a foreach loop
{
<tr class="contacts-record">
<td>
<input type="hidden" name="Index" value="@i" /> // add this
@Html.TextBoxFor(a => a[i].LASTNAME)
@Html.HiddenFor(a => a[i].DOB_NBR)
@Html.ValidationMessageFor(a => a[i].LASTNAME, "", new { @class = "text-danger" })
</td>
.... // other td elements
<tr>
}
For more information on binding to collections, refer Model Binding To A List, and if your also looking to dynamically add items to the collections, refer the answers here and here
有关绑定到集合的更多信息,请参考到列表的模型绑定,如果还想动态地向集合添加项,请参考这里和这里的答案
Side note: remove the id
attribute from your 'Delete' button. Your creating duplicate id
attributes which is invalid html. Also remove the scripts for jquery.validate.min.js
and jquery.validate.unobtrusive.min.js
because you have already added them using @Scripts.Render("~/bundles/jqueryval")
, however you need to ensure that jquery-1.10.2.min.js
is rendered first, preferably using @Scripts.Render("~/bundles/jquery")
. In addition, all the scripts should be inside @section Scripts {
侧边注:从“删除”按钮中删除id属性。创建无效的html的重复id属性。还可以删除jquery.validate.min的脚本。js和jquery.validate.unobtrusive.min。因为您已经使用@Scripts.Render(“~/bundle /jqueryval”)添加了它们,但是您需要确保jquery-1.10.2.min。首先呈现js,最好使用@Scripts.Render(“~/bundle /jquery”)。此外,所有脚本都应该在@section脚本{
#1
1
By default, the DefaultModelBinder
will only bind collections when the indexers are zero-based and consecutive. In your case, when you remove the 4th row, your indexers are 0, 1, 2, 4 and 5 so only the first 3 are bound. You can override this behavior by adding a hidden input for the indexer, which allows the DefaultModelBinder
to match up non-consecutive indexers.
默认情况下,DefaultModelBinder只在索引器为零和连续时绑定集合。在你的情况下,当你移除第4行时,你的索引器是0、1、2、4和5,所以只有前3个是绑定的。您可以通过为索引器添加隐藏的输入来覆盖此行为,这允许DefaultModelBinder匹配非连续索引器。
Change your loop to
改变你的循环
for (int i = 0; i < Model.Count; i++) // do not use a foreach loop
{
<tr class="contacts-record">
<td>
<input type="hidden" name="Index" value="@i" /> // add this
@Html.TextBoxFor(a => a[i].LASTNAME)
@Html.HiddenFor(a => a[i].DOB_NBR)
@Html.ValidationMessageFor(a => a[i].LASTNAME, "", new { @class = "text-danger" })
</td>
.... // other td elements
<tr>
}
For more information on binding to collections, refer Model Binding To A List, and if your also looking to dynamically add items to the collections, refer the answers here and here
有关绑定到集合的更多信息,请参考到列表的模型绑定,如果还想动态地向集合添加项,请参考这里和这里的答案
Side note: remove the id
attribute from your 'Delete' button. Your creating duplicate id
attributes which is invalid html. Also remove the scripts for jquery.validate.min.js
and jquery.validate.unobtrusive.min.js
because you have already added them using @Scripts.Render("~/bundles/jqueryval")
, however you need to ensure that jquery-1.10.2.min.js
is rendered first, preferably using @Scripts.Render("~/bundles/jquery")
. In addition, all the scripts should be inside @section Scripts {
侧边注:从“删除”按钮中删除id属性。创建无效的html的重复id属性。还可以删除jquery.validate.min的脚本。js和jquery.validate.unobtrusive.min。因为您已经使用@Scripts.Render(“~/bundle /jqueryval”)添加了它们,但是您需要确保jquery-1.10.2.min。首先呈现js,最好使用@Scripts.Render(“~/bundle /jquery”)。此外,所有脚本都应该在@section脚本{