5

I have a table and I want to clone the last line of it after the Add New link is pressed. It works completely fine when I have only TextBoxes in my rows but it doesn't when there's a dropdown. Please help me to modify the jquery code. Here's the code of the table:

<div><a href="#" id="addNew">Add New</a></div>
                <table id="dataTable">
                    <tr>
                        <th>Item</th>
                        <th>Cost</th>
                        <th></th>
                    </tr>
                    @if (Model != null && Model.Count > 0)
                    {
                        int j = 0;
                        foreach (var i in Model)
                        {
                            <tr>
                                <td>@Html.DropDownListFor(a => a[j].fk_purchase_id, (SelectList)ViewBag.fk_purchase_id, null, htmlAttributes: new { @class = "form-control"})</td>
                                <td>@Html.TextBoxFor(a => a[j].cost, htmlAttributes: new { @class = "form-control" })</td>
                                <td>
                                    @if (j > 0)
                                    {
                                        <a href="#" class="remove">Remove</a>
                                    }
                                </td>
                            </tr>
                            j++;
                        }
                    }
                </table>

And here's the code that needs some improvement:

 <script>
        $(function () {
            //1. Add new row
            $("#addNew").click(function (e) {
                e.preventDefault();
                var $tableBody = $("#dataTable");
                var $trLast = $tableBody.find("tr:last");
                var $trNew = $trLast.clone();
                alert($trNew.html);
                var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
                $trNew.find("td:last").html('<a href="#" class="remove">Remove</a>');
                $.each($trNew.find(':input'), function (i, val) {
                // Replaced Name
                var oldN = $(this).attr('name');
                var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
                 $(this).attr('name', newN);
                 //Replaced value
                var type = $(this).attr('type');
                if (type.toLowerCase() == "text") {
                 $(this).attr('value', '');
                  }
                  });

                $trLast.after($trNew);
            });

        });
    </script>

I tried to modify this line whith changing input to select, but it didnt help

var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);

Amelie
  • 61
  • 4
  • 1
    I would recommend a different approach as per the answers [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) and [here](http://stackoverflow.com/questions/40539321/a-partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892) –  May 05 '17 at 02:08

1 Answers1

2

First add tbody in your table like:

        <table id="dataTable">
        <thead>
            <tr>
                <th>Item</th>
                <th>Cost</th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            @if (Model != null && Model.Count > 0)
            {
                int j = 0;
                foreach (var i in Model)
                {
                    <tr>
                        <td>@Html.DropDownListFor(a => a[j].fk_purchase_id, (SelectList)ViewBag.fk_purchase_id, null, htmlAttributes: new { @class = "form-control"})</td>
                        <td>@Html.TextBoxFor(a => a[j].cost, htmlAttributes: new { @class = "form-control" })</td>
                        <td>
                            @if (j > 0)
                            {
                                <a href="#" class="remove">Remove</a>
                            }
                        </td>
                    </tr>
                    j++;
                }
            }
         </tbody>
        </table>

And your script is:

    <script>
    $(function () {
        $("#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 + '].');
                $('#dataTable tbody').append(tr);
            }
        });

    });
</script> 
Ashiquzzaman
  • 5,129
  • 3
  • 27
  • 38
  • Thanks @Ashiquzzaman, it helped with copying, although now there's another problem with passing data to controller. **It only passes maximum 2 model items even if I have 4 lines copied.** Before with only textboxes I could send all the items.. It's still someting with the jquery, probably with index... – Amelie May 05 '17 at 08:50
  • can you please show me your html. after 4 copy?@Amelie – Ashiquzzaman May 05 '17 at 08:54
  • here's the full view that I am using : https://jsfiddle.net/aiste/mp5cx5sL/ @Ashiquzzaman – Amelie May 05 '17 at 09:17
  • sorry may be you not understand what i want. please show me your `html` after copy 4 from your browser.you can get it by `inspect` element. – Ashiquzzaman May 05 '17 at 09:23
  • https://jsfiddle.net/aiste/6cvqpy6f/ @Ashiquzzaman, now it is html of the table with copied 4 items – Amelie May 05 '17 at 09:35
  • @Amelie i update my answer. please try this. I already test it. – Ashiquzzaman May 05 '17 at 09:56