1

At first I was trying to use .submit() but read that it won't work with dynamically generated elements (after the DOM is ready). So I tried .on(). It works in one script, but I'm having trouble getting it to work with button clicks.

The forms are placed dynamically. I'm using bootstrap-tables to load JSON into a table, an the form is part of the JSON that gets passed. There are up to 100 forms on each page.

Here's my form and the table structure it's in:

<table id="report-table">
    <tbody>
        <tr>
            <td></td><td></td><td></td>
            <td>
                <form>
                    <input type="text" />
                    <button type="submit" id="add_tag">Add Tag</button>
                </form>
            </td>
        </tr>
    </tbody>
</table>

I've tried:

//I'm assuming this didn't work because the form was generated using JS
$(".add_tag").click( function(e) {
    e.preventDefault();
    alert("button clicked");
});

//Same reasoning as above
$("form").submit( function(e) {
    e.preventDefault();
    alert("button clicked");
});

//Not sure why this worn't work
$( "#report-table tbody tr td form button" ).on( "click", function(e) {
    e.preventDefault(); //this doesn't even work.
    alert("button clicked");
});

Any ideas?

scniro
  • 16,844
  • 8
  • 62
  • 106
KingRichard
  • 1,214
  • 2
  • 14
  • 25
  • Have you tried changing the button to `type="button"`? – scniro Feb 02 '15 at 21:57
  • 1
    You need to use event delegation. See my answer here: http://stackoverflow.com/questions/24365447/no-jquery-events-handled-on-html-from-ajax-results/24365636#24365636 – jme11 Feb 02 '15 at 21:57
  • @jme11 that did the trick. Can you explain the difference between `$("#report-table tbody tr td form button").on("click", function(e)` and `$("#report-table").on("click", "button", function(e)` ? – KingRichard Feb 02 '15 at 22:00
  • 1
    A very thorough explanation is here as well: http://learn.jquery.com/events/event-delegation/. – jme11 Feb 02 '15 at 22:01
  • You need to rebind the new HTML to the jQuery event whenever you generate the new HTML. – Travis Pettry Feb 02 '15 at 22:06

2 Answers2

1

To answer the question in the comments, the difference is that the handler needs to be attached to something that is in the DOM when the page is actually loaded. Since your button doesn't exist initially, the handler can't be registered to it directly unless you add the handler after the button has been created and added to the DOM.

Nevertheless, since you have a lot of these buttons, event delegation is going to be more performant for you. Instead of registering 100 or so individual handlers, one for each button, you only have one for your entire #report-table.

This method takes advantage of the fact that events "bubble" up through all of the ancestors (parents and parents of parents) of the element that dispatched the event. The event object contains a reference to that original element that dispatched it.

So, when you use the delegation pattern:

$("#report-table").on("click", "button", function(e)...

the report-table element gets the click once the event bubbles up to it. Then it reads the event object and checks if the element that dispatched the event matches the element in the second argument of the on method, which in this case is your button. If it matches, it runs the callback function, and if not it doesn't.

As I said in the comments, there's an excellent and much more detailed explanation on the jquery.com site.

jme11
  • 17,134
  • 2
  • 38
  • 48
1

here are two observations

  1. "add_tag" is an 'id', not a 'class'

Change from

$(".add_tag").click( function(e) {
    e.preventDefault();
    alert("button clicked");
});

to

$("#add_tag").click( function(e) {
    e.preventDefault();
    alert("button clicked");
});
  1. Agreed with other person's answer/comments using event delegation.

change from

$( "#report-table tbody tr td form button" ).on( "click", function(e) {

to

$("#report-table").on("click", "button", function(e) {
Lumi Lu
  • 3,289
  • 1
  • 11
  • 21