1

EDIT:

I've a table with which I dynamically add / remove rows in a table using jQuery in MVC4. When I do POST the rows are not stored completely,

Example: I add 10 rows to the table and delete the 7th, theoretically there are only 9 rows left. The problem I have is that regardless of the row that I delete, only the rows before that (1 to 6) are saved and it is supposed to save all the rows that are in the table (1 to 9).

enter image description here

I was looking for debbug and noticed that the Input ID is not updated, I got the following results.

        <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">

As you can see, the position I selected was eliminated but the input ID was not updated, so I need it to be as follows.

        <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">

Is there any way to update the id values ​​correctly?

Here's my code:

 <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 Code:

    $(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 -
});
6
  • When you debug, what is actually posted to the server? Does that post contain all of the expected data, or only the first 7 rows of data? How are you posting it? What is the actual HTML? (Both before and after the "remove" operation?) The code implies that you have only one #remove button, but the picture you're showing suggests that you have multiple "remove" buttons. If you're re-using id values on the page then your markup is invalid anyway and you'll want to correct that before debugging anything else. Commented Jul 20, 2021 at 21:40
  • @David Yes, each row has a Remove action but when I do POST the rows are not stored completely, in the example I put I made it with 10 rows and delete the 7th. The problem I've is that regardless of the row that I delete, only the rows before that one are saved and it is supposed to save all the rows that are in the table. Commented Jul 20, 2021 at 21:53
  • Yes, you indicated that much in the question. But can you debug to further narrow the problem and can you provide relevant HTML markup further demonstrating the problem? It's also highly recommended that you correct any invalid HTML markup, as that could easily be causing this or other problems. Commented Jul 20, 2021 at 21:56
  • All Tags are correct but I really do not know why the problem happens when saving the data, it is somewhat frustrating because I can not find the problem Commented Jul 21, 2021 at 22:50
  • 1
    I have updated my question, I hope now explained what's my issue Commented Jul 22, 2021 at 22:11

1 Answer 1

3

The core of the issue here is that ASP.NET MVC's model binding stops building a collection when it finds a gap in the numbering. So the client is successfully POSTing the values to the server, but the server-side framework is ignoring them so they're lost before they reach the controller action method.

A solution is going to depend on what your server-side code is expecting and how it uses the data. Whether that code knows how to identify and handle the missing records and how you're updating the backing data. But currently that's not in the scope of the question and what you're specifically asking is how to re-number the values client-side, so let's focus on that.

You already have and call a function to "re-number rows" after deleting an entry:

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

It just doesn't re-number anything significant. All it's doing is showing a number to the user, not re-numbering any indexes sent to the server. But you can use the same function to do exactly that. Perhaps something like this:

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");
  });
}

The new line of code is similar to the previous one in that it starts at the "current row", finds a <td> cell (this time the second cell, not the first one), and modifies something in that cell. This time it finds an <input> in the cell and sets its name attribute to a value based on the i index. So the resulting values should be "[0].HW_SQ", "[1].HW_SQ", "[2].HW_SQ", etc.

You can add more lines to that function using this same approach to re-number the rest of the inputs. At that point it should then be up to your server-side code to know how to interpret the newly-numbered records and sync back to the data as needed.


As an aside, your HTML markup is currently invalid which could lead to more bugs in the future. Specifically, this element has an id that gets repeated multiple times:

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

Fortunately the element already has a class attribute that you can use. So remove the id attribute entirely and use the class to select the element in your JavaScript:

$(document).on('click', '.remove', function (e) {
  //...
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, it works like a charm! As you mentioned, I used the "numberRows" function only for the aesthetic index in HTML but now you need to modify the value internally for each <input> I didn't know how to do it but now I can save my data correctly updating all the fields. Thanks for all your help and very relevant information in your answer, Have a nice day David!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.