0

I'm trying to build an app that helps people list their expenses in a specific order. How can I allow them to add rows at specific points?

Starting with a simple HTML table like this:

<table id='exptable'>
<tr>
  <td>(date)</td>
  <td><input type='text' placeholder='Expense type (rent, groceries, etc.)'/></td>
  <td><input type='number' value='.00'/></td>
  <td><input type='button' class='addrow' value='Add Row Below'/></td>
  <td><input type='button' class='delrow' value='Delete' /></td>
</tr>
<tr>
  <td>(date)</td>
  <td><input type='text' placeholder='Expense type (rent, groceries, etc.)'/></td>
  <td><input type='number' value='.00'/></td>
  <td><input type='button' class='addrow' value='Add Row Below'/></td>
  <td><input type='button' class='delrow' value='Delete' /></td>
</tr>
</table>

My "delete button" works fine with this JQuery:

$('.delrow').click(function(){
    $(this).parent().parent().remove();
});

As for the insert button, They will ultimately be able to reorder the rows, so assigning each row a unique ID seems infeasible. Here's the atrocious code I have now:

$('.addrow').click(function(){
  $("<tr><td></td><td><input type='text' placeholder='Inserted Row'/></td><td><input type='number' value='.00' class='dollar ' size='8'/></td><td><input type='button' class='addrow' value='Add Row Below'/></td><td><input type='button' class='delrow' value='Delete' /></td></tr>").insertAfter(this.parentNode.parentNode);
});

This DOES insert the row where I want it. However, neither of the buttons in the new row work. Why not? Is there a smarter way to insert a row wherever you want?

jsfiddle

Cobra
  • 367
  • 3
  • 10
  • 1
    Possible duplicate of [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Heretic Monkey Apr 08 '18 at 03:00

1 Answers1

1

The problem is that your code that binds the click:

$('.delrow').click(function(){
    $(this).parent().parent().remove();
});

Only works for those elements matching .delrow that are present in the DOM when it is called. It will not work for any matching elements that are added later.

Instead, use a delegated event where you put the listener on a shared parent and delegate down to the targeted selector. Something like this:

$('#exptable').on('click', '.delrow', function(){
    $(this).parent().parent().remove();
});

...should be sufficient for your needs. Also, I'd recommend ditching the chained .parent().parent() and replace it with something less fragile, like .closest: $(this).closest('tr').remove();

Alexander Nied
  • 7,538
  • 2
  • 22
  • 38