使用jQuery在asp.net mvc中动态删除表格行

3
我有一个表格,可以动态添加和删除行:
@model AHBReports.Models.AdjustmentModel
@using (Html.BeginForm())
{
    <table id="container">
         @Html.EditorFor(model => model.Adjustments)
    </table>
    <div >
        <input type="button" id="btnAdd" value="+ Add" />
        <input type="submit" value="Submit" />
    </div>
}

编辑器模板:

@model AHBReports.Models.Adjustment
<tr>
    <td>@Html.HiddenFor(x => x.Id, new { @class = "iHidden" })</td>
    <td>@Html.AutocompleteFor(model => model.BRANCH, "GetBranches", "Report700H")</td>
    <td>@Html.EditorFor(model => model.Amount)</td>
    <td><a onclick="removeRow(this)">x</a></td>
</tr>

表格操作脚本:

<script type="text/javascript">

function removeRow(selector)
{
    if ($('#container tr').length > 1) 
    {
        $(selector).closest('tr').remove();
    }       
}
$(document).ready(function () {       

    $("#btnAdd").click(function (e) {           

        var ind = $("#container tr:last").find("input.iHidden").val();
        var itemIndex = parseInt(ind);
        itemIndex++;
        console.log(itemIndex);
        e.preventDefault();
        var newItem = $("<tr>"+
            "<td><input id='Adjustments_" + itemIndex + "__Id' type='hidden' value='"+itemIndex+"' class='iHidden'  name='Adjustments[" + itemIndex + "].Id' /></td>" +
            "<td><input type='text' id='Adjustments_" + itemIndex + "__BRANCH' name='Adjustments[" + itemIndex + "].BRANCH' data-autocomplete-url='@Url.Action("GetBranches", "Report700H")'/></td>" +
            "<td><input type='text' id='Adjustments_" + itemIndex + "__Amount' name='Adjustments[" + itemIndex + "].Amount'/></td>" +
            "<td><a onclick='removeRow(this)'>x</a></td>" +
            "</tr>");
        $("#container").append(newItem);


    });

});

我的添加/删除功能在视图上看起来很好,当我在POST方法中接受集合时也能正常工作:

 public ActionResult Adjust(AdjustmentModel model)
{
       //working with model.Adjustments
}

我收到了正确的数值。但是,当我尝试删除表格中间的某一行并提交表单时,我只会收到已经删除行上方的元素,例如:

id  branch amount
0   aaa    500
1   bbb    200
2   ccc    300 --deleted this row
3   ddd    400

Collection接收:

id  branch amount
0   aaa    500
1   bbb    200

所以,最后一行缺失了。我做错了什么吗?非常感谢。

1
它在 fiddle 上运行得非常好。 - Regent
我相信Gyuzal的意思是他的JQuery代码删除了正确的行,但在向服务器提交后,选择删除的行下面的任何行也被删除了,对吗? - Gjohn
@Gjohn 你说得对,(我是女性 :)) - Gyuzal
嗯,我没有注意到form。实际上,因为有@using (Html.BeginForm())等内容,而不是渲染的HTML(这很重要,应该显示出来)... - Regent
好的,让我们用<form>将之前的代码包装起来,它仍然可以工作:更新后的fiddle - Regent
3个回答

5

当您删除的行包含模型输入并且输入根据索引具有名称和ID时。

因此,当您删除行时,必须更新在删除行之后的行中的输入名称和ID。 或者使用新的索引名称从删除行开始重新生成下一个所有行。

请使用以下函数替换您的删除功能:

function removeRow(selector) {
        if ($('#container tr').length > 1) {
            $(selector).closest('tr').remove();
            var itemIndex =0;
            $('#container tr').each(function(){
                var this_row = $(this);
                this_row.find('input[name$=".BRANCH"]').attr('name','Adjustments[' + itemIndex + '].BRANCH');//replace name of input that ends the name BRANCH
                this_row.find('input[name$=".Amount"]').attr('name','Adjustments[' + itemIndex + '].Amount');
                this_row.find('input[name$=".Id"]').attr('name', 'Adjustments[' + itemIndex + '].Id');
                itemIndex ++;
            });
        }
    }

2

集合的索引器必须从零开始,并且必须连续,除非您使用一个Index属性,其中Index的值等于索引器。例如:

<input ... name="Adjustments[0].ID" ..>
<input ... name="Adjustments[2].ID" ..>

如果您为对象添加索引属性,则可以正确地提交回服务器。

<input ... name="Adjustments[0].ID" ..>
<input ... name="Adjustments[0].Branch" ..>
<input ... name="Adjustments[0].Index" value="0"..>

<input ... name="Adjustments[2].ID" ..>
<input ... name="Adjustments[2].Branch" ..>
<input ... name="Adjustments[2].Index" value="2"..>

然后集合将正确地进行回发

由于您无法在EditorTemplate中访问索引器,因此需要在主页面中使用loop生成控件

for (int i = 0; i < Model.Adjustments.Count; i++)
{
  var name = string.Format("Adjustments[{0}].Index", i);
  @Html.HiddenFor(m => m[i].ID)
  ....
  <input type=hidden name="@name" value="@i" />
}

你还需要修改脚本,将隐藏输入框包含在 Index 属性中。与其基于现有行的数量确定 itemIndex 的值,不如基于一个唯一的值。例如:
$("#btnAdd").click(function (e) {
  var itemIndex = (new Date()).getTime();

0

你可以给这一行一个唯一的ID。

var newItem = $("<tr id='row"+itemIndex+"'>"+
            "<td><input id='Adjustments_" + itemIndex + "__Id' type='hidden' value='"+itemIndex+"' class='iHidden'  name='Adjustments[" + itemIndex + "].Id' /></td>" +
            "<td><input type='text' id='Adjustments_" + itemIndex + "__BRANCH' name='Adjustments[" + itemIndex + "].BRANCH' data-autocomplete-url='@Url.Action("GetBranches", "Report700H")'/></td>" +
            "<td><input type='text' id='Adjustments_" + itemIndex + "__Amount' name='Adjustments[" + itemIndex + "].Amount'/></td>" +
            "<td><a onclick='$('#row"+ itemIndex +").remove();'>x</a></td>" +
            "</tr>');

实际上,这对我创建的类似页面很好用。

问候


onclick="function_name()" 是处理事件的过时方式。你在 onclick 中编写了代码行 - 这甚至更糟... - Regent
在我的情况下,ID没有帮助。 - Gyuzal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接