MVC 4 上 HTML Table 的问题 - 使用 jQuery 动态删除行

Problem with HTML Table on MVC 4 - Deleting row dynamically using jQuery

编辑:

我有一个 table,我使用 MVC4 中的 jQuery 在 table 中动态添加/删除行。 当我执行 POST 时,行未完全存储,

示例:我在table中添加了10行并删除了第7行,理论上只剩下9行。 我遇到的问题是,无论我删除了哪一行,都只会保存之前的行(1 到 6),并且应该保存 table(1 到 9)中的所有行。

我正在寻找调试并注意到输入 ID 没有更新,我得到了以下结果。

        <input name="[0].HW_SQ">
        <input name="[1].HW_SQ">
        <input name="[2].HW_SQ">
        <input name="[3].HW_SQ">
        <input name="[4].HW_SQ">
        <input name="[5].HW_SQ">
        <input name="[7].HW_SQ">
        <input name="[8].HW_SQ">
        <input name="[9].HW_SQ">

如您所见,我选择的位置被淘汰了,但输入的ID没有更新,所以我需要如下。

        <input name="[0].HW_SQ">
        <input name="[1].HW_SQ">
        <input name="[2].HW_SQ">
        <input name="[3].HW_SQ">
        <input name="[4].HW_SQ">
        <input name="[5].HW_SQ">
        <input name="[6].HW_SQ">
        <input name="[7].HW_SQ">
        <input name="[8].HW_SQ">

有什么方法可以正确更新id值吗?

这是我的代码:

 <div><a href="#" id="addNew"><input type="button" value="Add"/></a></div>
<table id="dataTable">
        <thead>
        <tr>
            <th>#</th>
            <th>SEQ</th>
            <th>Brand</th>
            <th>Serial</th>
            <th>Model</th>
            <th>Year Model</th>
            <th>Status</th>                
            <th>Place</th>
            <th>Location</th>
            <th>FA Tag</th>
            <th>Security Tag</th>
            <th>Date Acquisition</th>
            <th>Price</th>
            <th>Description</th>
        </tr>
        </thead>
        <tbody id="mytbody">
        @if (Model != null && Model.Count > 0)
        {
            int j = 0;
            int index = 1;
            
            foreach (var p in Model)
            {
               <tr>
                    <td style="text-align:center;">@index</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_SQ)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_BRAND)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_SERIAL)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_MODEL)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_YEAR)</td>                        
                    <td>@Html.TextBoxFor(a => a[j].HW_STATUS)</td>                                               
                    <td>@Html.TextBoxFor(a => a[j].HW_PLACE)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_LOCATION)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_FA_TAG)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_SECURITY_TAG)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_DATE_ITEM_ADQUISITION)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_PRICE)</td>
                    <td>@Html.TextBoxFor(a => a[j].HW_DESCRIPTION)</td>
                    <td>          
                         <a href="#" id="remove" class="remove">Remove</a>    
                    </td>                     
               </tr>
                index += 1;
            }
        }
        </tbody>
        </table>
                <center><input type="submit" value="Save" id="sendinv"/></center>

jQuery代码:

    $(document).ready(function () {

    function numberRows($t) {
    $t.find("tr").each(function (i, el) {
        $(el).find("td").eq(0).html((i + 1));
    });
    }

    //- Start Table Add, delete buttons -

    $("#addNew").click(function (e) {
        e.preventDefault();
    var last = $('#dataTable>tbody>tr:last');
    if (last.length > 0) {
        var name = last.children().find('input,select')[0].name;
        var index = Number(name.replace(/[^0-9]/gi, '')) + 1;
        var tr = ('<tr>' + last.html().replace(/[0-9]+__/gi, index + '__') + '</tr>').replace(/\[[0-9]+\]+[.]/gi, '[' + index + '].');
        numberRows($('#dataTable tbody').append(tr));
    }
    });

    $(document).on('click', '#remove', function (e) {
        e.preventDefault();
        if ($('#dataTable>tbody>tr').length > 1) {
            //$(this).parent().parent().remove();
            $(this).closest('tr').remove();
            numberRows($('#dataTable tbody'));
            return false;
        }
        else {
            //$(this).parent().parent().show();
            alert('Form must have at least one row')
            numberRows($('#dataTable tbody'));
        }
    });
    //- End Table Add, delete buttons -
});

这里问题的核心是ASP.NET MVC 的模型绑定在发现编号间隙时停止构建集合。因此,客户端成功将值发布到服务器,但服务器端框架忽略了它们,因此它们在到达控制器操作方法之前就丢失了。

解决方案将取决于您的服务器端代码期望什么以及它如何使用数据。该代码是否知道如何识别和处理丢失的记录以及您如何更新支持数据。但是目前这不在问题的范围内,您具体要问的是如何在客户端重新编号这些值,所以让我们专注于此。

您已经拥有并调用了一个函数来在删除条目后“重新编号行”:

function numberRows($t) {
  $t.find("tr").each(function (i, el) {
    $(el).find("td").eq(0).html((i + 1));
  });
}

它只是没有重新编号任何重要的东西。它所做的只是向用户显示一个数字,而不是对发送到服务器的任何索引重新编号。但是您可以使用相同的功能来做到这一点。也许是这样的:

function numberRows($t) {
  $t.find("tr").each(function (i, el) {
    $(el).find("td").eq(0).html((i + 1));
    $(el).find("td").eq(1).find("input").prop("name", "[" + i + "].HW_SQ");
  });
}

新的代码行与上一行类似,它从“当前行”开始,找到一个 <td> 单元格(这次是第二个单元格,而不是第一个),并修改那个牢房里的东西。这次它在单元格中找到 <input> 并将其 name 属性设置为基于 i 索引的值。所以结果值应该是“[0].HW_SQ”、“[1].HW_SQ”、“[2].HW_SQ”等

您可以使用相同的方法向该函数添加更多行以重新编号其余输入。届时,您的服务器端代码应该知道如何解释新编号的记录并根据需要同步回数据。


顺便说一句,您的 HTML 标记当前无效,这可能会在未来导致更多错误。具体来说,此元素有一个重复多次的 id

<a href="#" id="remove" class="remove">Remove</a>

幸运的是,该元素已经具有您可以使用的 class 属性。因此,完全删除 id 属性并使用 class 到 select JavaScript:

中的元素
$(document).on('click', '.remove', function (e) {
  //...
});