Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing dynamically added row from a table using jquery

My code adds a row to table when a plus is pressed, and it adds it with the right references so when I submit my form data I know what data is what. The minus I am having a bit difficulty getting it to work in removing the row just added or another row previously added from the table.

I thought maybe its my .bind in that last line of the addRow function as I saw here it might should be a .on ?

Issue while removing a dynamically added row from a html table using jquery

In either case my code is here:

   <script language='javascript' type='text/javascript'>

        $(document).ready(function () {

            function addRow() {
                var $myTable = $("#myTable").find('tbody');
                var parent = $(this).parent("td").parent("tr").attr("id");
                var newRowID = $myTable.children("tr").length + 1;

                var $newRow = $("<tr id='regFacEmpType" + newRowID + "' data-parent-row='" + parent + "'>");
                $newRow.append($("<td align='center'>611000</td>"));
                $newRow.append($("<td class='style1'><input type='text' name='RegEmpType" + newRowID + "' size='15' data-emp-type='Regular' /></td>"));
                //see the data-emp-type not sure how else to know what is coming back unless name is going to be dynamically generated here using  a counter.  Should
                //only be one type of each field, so instead of EmpType being generic:  EmpTypeRegular1 and if they add another employee then EmpTypeRegular2 etc.

                $newRow.append($("<td><input type='checkbox' name='RegEmpIDC" + newRowID + "' value='true' /></td>"));
                $newRow.append($("<td align='center' id='RegEmpAgencyBudgt" + newRowID + "'>$43,0000</td>"));
                $newRow.append($("<td align='center' id='RegEmpRowBdgt" + newRowID + "'>$3,0000</td>"));
                $newRow.append($("<td class='style1' id='RegEmpRowAdjBudget" + newRowID + "'><input type='text' name='AdjustedBudgetRegularEmpType" + newRowID + "' /></td>"));
                $newRow.append($("<td class='style1' id='RegEmpRowComments" + newRowID + "'><input type='text' name='RegEmpComments" + newRowID + "' /></td>"));
                $newRow.append($("<td></td>").append($("<button class='addRegular' type='button'>+</button>").bind("click", addRow))); //make it where any plus subsequently added will add a row
                $newRow.append($("<td></td>").append($("<button class='removeRegular' id='removeRegular" + newRowID +"' type='button'>-</button>").bind("click", removeRegularRow(newRowID))));
                $myTable.append($newRow);
            };


            //for some reason this is called everytime I click the PLUS also it does nothing?
            function removeRegularRow(index) {
                        $("#regFacEmpType" + index).remove();
            };



            $(".addRegular").on("click", addRow); //make it so the default row adds a new one.
        });
</script>
</head>
<body>
    <FORM action="" method="post">

    <table id='myTable'>

            <tbody>
                <tr id="FacultyEmployees">
                    <th align="center" class="style1">Index Number</th>
                    <th align="center" class="style1">Faculty Type</th>
                    <th align="center" class="style1">IDC</th>
                    <th align="center" class="style1">Agency Budgeted Amount</th>
                    <th align="center" class="style1">PI Budgeted Amount</th>
                    <th align="center" class="style1">PI Adjusted Budget</th>
                    <th align="center" class="style1">Comments</th>
                </tr>
                <tr id="regFacEmpType1" data-child-type='regExemptEmpType1' data-parent-type='regFacEmpType1'>
                    <!-- next row would be regExemptEmpType1 etc -->
                    <td align="center">611000</td>
                    <td align="center">Regular</td>
                    <td><input type="checkbox" name="IDC" value="true" /></td>
                    <td align="center" id="agencyBudgeted1">$43,0000</td>
                    <td align="center" id="piBudgetedAmount1">$33,0000</td>
                    <td id="piAdjustedBudget1"><input type="text" name="PI Adjusted Budget" width="5" /></td>
                    <td class="style1"><input type="text" name="Comments" id="comments1" size="15" /></td>
                    <td><button type='button' class="addRegular">+</button></td>                    
                </tr>
            </tbody>

        </table>
        <button type="submit"/> Submit </button>
        </FORM>
like image 214
Codejoy Avatar asked Oct 05 '15 17:10

Codejoy


People also ask

How can remove dynamic row from table in jQuery?

// Removing the current row. $( this ). closest( 'tr' ). remove();

How do I remove a row from a table in jQuery?

The jQuery remove() method is used to remove a row from HTML table. jQuery remove() Method: This method removes the selected elements alongwith text and child nodes. This method also removes data and events of the selected elements.


2 Answers

Solving the issue

Concerning your JavaScript code:

  • Remove the bind() function;
  • Remove the removeRegularRow() function;
  • Add the following on('click'.. event inside $(document).ready:

    $("#myTable").on('click', '.removeRegular', function(){
    
        $(this).parent().parent().remove();
        // It's faster with: $(this).closest('tr').remove();
    
    });
    

On why this solves the issue at hand

The problem is that this row of elements is dynamically inserted and only after the DOM had everything loaded and was ready. In a simple way, your algorithm won't find the desired HTML inserted everything was loaded.

With $('.some_parent_element').on('click', '.element_desired', function(){...}); you can circumvent this problem and do whatever you want with the element. That is, let's stick with the idea of suitable for all ages, shall we? :P

The answer you mentioned has a very good and concise explanation. Try to understand that answer because you will need to understand for future coding.

On why it's faster with closest

Well, we have a great answer here in SO explaining the "why" so I will link to it. But, to sum it up, it revolves around searching the entire document or an specific area of the document. There is also the library layers that needs to be dealt with to finally get where you want. As an addendum, check this performance test.

The docs says:

parent() gets the parent of each element in the current set of matched elements, optionally filtered by a selector.

closest() For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.

There are ways to do it faster than parent() and closest() that relies on 'native' Java Script. But you should always take into account readability as well as bosses and clients stubbornness...

Also take into account your application's target audience. Scalability is important, of course, but even if something is slower than some other, if you application is not huge or doesn't have a lot of data to deal with, it won't really matter what you use. Just make sure to avail it properly and constantly to change whenever needed.

Testing the rewritten code

You can verify that the code, with the changes, now works. Just click on the button "Run code snippet" down below.

$(document).ready(function () {

    		var index;
    
            function addRow() {
                var $myTable = $("#myTable").find('tbody');
                var parent = $(this).parent("td").parent("tr").attr("id");
                var newRowID = $myTable.children("tr").length + 1;
                
                index = newRowID;

                var $newRow = $("<tr id='regFacEmpType" + newRowID + "' data-parent-row='" + parent + "'>");
                $newRow.append($("<td align='center'>611000</td>"));
                $newRow.append($("<td class='style1'><input type='text' name='RegEmpType" + newRowID + "' size='15' data-emp-type='Regular' /></td>"));
                //see the data-emp-type not sure how else to know what is coming back unless name is going to be dynamically generated here using  a counter.  Should
                //only be one type of each field, so instead of EmpType being generic:  EmpTypeRegular1 and if they add another employee then EmpTypeRegular2 etc.

                $newRow.append($("<td><input type='checkbox' name='RegEmpIDC" + newRowID + "' value='true' /></td>"));
                $newRow.append($("<td align='center' id='RegEmpAgencyBudgt" + newRowID + "'>$43,0000</td>"));
                $newRow.append($("<td align='center' id='RegEmpRowBdgt" + newRowID + "'>$3,0000</td>"));
                $newRow.append($("<td class='style1' id='RegEmpRowAdjBudget" + newRowID + "'><input type='text' name='AdjustedBudgetRegularEmpType" + newRowID + "' /></td>"));
                $newRow.append($("<td class='style1' id='RegEmpRowComments" + newRowID + "'><input type='text' name='RegEmpComments" + newRowID + "' /></td>"));
                $newRow.append($("<td></td>").append($("<button class='addRegular' type='button'>+</button>").bind("click", addRow))); //make it where any plus subsequently added will add a row
                $newRow.append($("<td></td>").append($("<button class='removeRegular' id='removeRegular" + newRowID +"' type='button'>-</button>")));
                $myTable.append($newRow);
            };

    		$("#myTable").on('click', '.removeRegular', function(){
                
            	$(this).parent().parent().remove();
            
            });


            $(".addRegular").on("click", addRow); //make it so the default row adds a new one.
        });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<FORM action="" method="post">

    <table id='myTable'>

            <tbody>
                <tr id="FacultyEmployees">
                    <th align="center" class="style1">Index Number</th>
                    <th align="center" class="style1">Faculty Type</th>
                    <th align="center" class="style1">IDC</th>
                    <th align="center" class="style1">Agency Budgeted Amount</th>
                    <th align="center" class="style1">PI Budgeted Amount</th>
                    <th align="center" class="style1">PI Adjusted Budget</th>
                    <th align="center" class="style1">Comments</th>
                </tr>
                <tr id="regFacEmpType1" data-child-type='regExemptEmpType1' data-parent-type='regFacEmpType1'>
                    <!-- next row would be regExemptEmpType1 etc -->
                    <td align="center">611000</td>
                    <td align="center">Regular</td>
                    <td><input type="checkbox" name="IDC" value="true" /></td>
                    <td align="center" id="agencyBudgeted1">$43,0000</td>
                    <td align="center" id="piBudgetedAmount1">$33,0000</td>
                    <td id="piAdjustedBudget1"><input type="text" name="PI Adjusted Budget" width="5" /></td>
                    <td class="style1"><input type="text" name="Comments" id="comments1" size="15" /></td>
                    <td><button type='button' class="addRegular">+</button></td>                    
                </tr>
            </tbody>

        </table>
        <button type="submit"/> Submit </button>
        </FORM>
like image 163
José Avatar answered Oct 15 '22 09:10

José


When you get into multiple repeating elements in a page using ID to target elements is the least preferred approach.

It gets far more complicated trying to make ID's match and it is much simpler to make traverses based on classes and structure of repeating elements.

Also one handler can manage all repeating elements. The following can be placed anywhere in the code base ... once per page load

$(document).on('click','.removeRegular', function(){
     $(this).closest('tr').remove();  
});

Then on the tr you can add a database identifier that can be used for ajax requests

<tr data-id="serverIdValue">

And upgrade the handler:

$(document).on('click','.removeRegular', function(){
     var $row = $(this).closest('tr'), rowId = $row.data('id');
     // only remove once server update confirmed
     $.post('/api/row/delete', {id: rowId}, function(response){
          // validate response first then remove the row
          $row.remove();
     });          
});

Note the separation of concerns...no inline code required and no need to process this in any sort of loop

like image 26
charlietfl Avatar answered Oct 15 '22 08:10

charlietfl