0

Here is my code:

$(document).ready(function(){
    $("#add_tactic").click(function(){
        var i = ($('#tactic_commentary tr').length-3)/2+1;
        $("#tactic_commentary tr").eq(-1).before('<tr><td style="width: 180px"><div id="form_label">Tactic Name:</div></td><td style="width: 575px" class="auto-style1"><input maxlength="150" name="tactiname'+i+'" style="width: 565px" type="text" /></td></tr>');
        $("#tactic_commentary tr").eq(-1).before('<tr><td style="width: 180px"><div id="form_label" class="auto-style1">Tactic Description:</div></td><td style="width: 575px" class="auto-style1"><textarea name="tacticdescription'+i+'"></textarea></td></tr>');
    });
});

My #add_tactic is as follows:

<div id="add_tactic">Add Tactic</div>

when this page loads, the on click event works fine. If the dropdown in the form changes, it replaces the DIV container with a rebuilt form dependent on your choice. The on click function of add_tactic does not work when the table is reloaded. Table ID does not change. Is there something I have to do when removing an element so that events are bound to it when it returns?

Peter
  • 3
  • 2
  • 7

3 Answers3

4

Yes, there is. In jQuery we call it event delegation.

You can achieve event delegation by leveraging the use of jQuery's .on() In short, you need to bind the function to a static element that doesn't get removed/replaced. For this example, we'll use the document but for performance, you should target a closer static element.

$(document).on('click', '#add_tactic', function(){
    var i = ($('#tactic_commentary tr').length-3)/2+1;
    $("#tactic_commentary tr").eq(-1).before('<tr><td style="width: 180px"><div id="form_label">Tactic Name:</div></td><td style="width: 575px" class="auto-style1"><input maxlength="150" name="tactiname'+i+'" style="width: 565px" type="text" /></td></tr>');
    $("#tactic_commentary tr").eq(-1).before('<tr><td style="width: 180px"><div id="form_label" class="auto-style1">Tactic Description:</div></td><td style="width: 575px" class="auto-style1"><textarea name="tacticdescription'+i+'"></textarea></td></tr>');
});

This will ensure that the click event fires regardless of it being removed/replaced.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • 1
    If the element is part of a container that gets overwritten, it would be nontrivial to detach/reattach. This is probably the best approach. – landons Jun 12 '13 at 22:03
2

Do not call remove() or overwrite your html, but rather use the detach() method, which will remove the elements from the DOM, but keep the associated data/handlers in jQuery's memory.

var detachedHtml = $('#add_tactic').detach();
// later on...
$(parentContainer).append(detachedHtml);
Brad M
  • 7,857
  • 1
  • 23
  • 40
  • Also a solid alternative to my answer. +1. – Ohgodwhy Jun 12 '13 at 22:01
  • 1
    Your alternative is unquestionable cleaner and easier to implement. But...it's generally abused by developers who add a million events to the document. – Brad M Jun 12 '13 at 22:03
0

When you remove an element all the event handlers bound to it are removed too. Creating a new element, even in the same place with the same id, is exactly that: a new element. You'll need to bind the event handlers again for them to work.

Alternatively, you could bind the handler to a parent container and delegate.

For example:

$('body').on('click', '#add_tactic', function(e) {
    // your code here
});

This will operate for all instances of #add_tactic now or added at any time in the future. this will point to the #add_tactic element

You'd probably want to bind the handler to a container element closer to the #add_tactic element.

  • $("tactic_commentary_container").on("click","#add_tactic",(function(){ ... Is a container that never is removed, however It does not trigger the action properly. before or after removal/return – Peter Jun 12 '13 at 22:20
  • Where I've had trouble with delegated handlers it's always been down to some problem on my part in understanding the context I'm executing in. If you can post a simple example (Javascript & HTML) of what you're now doing I could take a look –  Jun 12 '13 at 23:30