1

I have a table which has checkboxes which get generated after a user imports files. The checkboxes are generated dynamically.

    $("input[name='child_user_id_fk[]']").change(function(){
        alert("test");
        $(this).closest("tr").toggleClass("checked", this.checked);
    });

This will work on any checkbox that was a part of the page when it were generated, but just not the ones generated with JQuery. How can I get this working?

user2924019
  • 1,581
  • 3
  • 24
  • 44

4 Answers4

1

You need to use the .on() method. This will attach any events to dynamically created elements.

$(document).on('change',"input[name='child_user_id_fk[]']",function(){
    alert("test");
    $(this).closest("tr").toggleClass("checked", this.checked);
});
Samuel Cook
  • 15,511
  • 6
  • 43
  • 58
  • 1
    I just found out about using `.live`. How does this differ? – user2924019 Dec 20 '16 at 21:01
  • 1
    `.live()` is deprecated. use `.on()` - http://api.jquery.com/live/ – Samuel Cook Dec 20 '16 at 21:01
  • `on` isn't deprecated but if you use it to bind lots of events to `document.body` you will have the exact same problem that `live` had. `on` is a general purpose tool for binding events, and with *any* event binding you only have two options: 1) wait until the element is on the page, or 2) bind the handler to an element higher in the DOM. The only "higher in the DOM" element you can consistently rely on is `document.body`, but every handler you bind to it will slow down the handling of every other event on the page (or at least every event that bubbles). This is why `live` was deprecated. – machineghost Dec 20 '16 at 21:18
1

The problem you're having is that your input isn't on the page when you hook up your event. As a result, it doesn't work.

As you noted, one way to fix the problem is to use live. What live does is add an event handler to the document body itself. Then, when any event from your input "bubbles up" to the body event handler, it handles it. This way even if the input isn't on the page when you add the event handler it still works (because the body is on the page).

But there's a problem: as others have noted, live is deprecated. The reason for this is simple: if you use live a lot (or even a medium amount) it can cause huge performance problems, because every event on your page has to go through every event handler you put on the body.

The solution is not to use live, but not to do what you're currently doing either. Instead, you simply want to hook up your event handler:

$("input[name='child_user_id_fk[]']").change(function(){
    alert("test");
    $(this).closest("tr").toggleClass("checked", this.checked);
});

AFTER you add your input to the page. For instance:

$('body').append('<input name="child_user_id_fk[]" />');
$("input[name='child_user_id_fk[]']").change(function(){
    alert("test");
    $(this).closest("tr").toggleClass("checked", this.checked);
});

Or to simplify it with chaining:

$('body').append('<input name="child_user_id_fk[]" />')
         .change(function(){
             alert("test");
             $(this).closest("tr").toggleClass("checked", this.checked);
         });

As long as you hook up the event handler to an element that's in the DOM (ie. as long as you do the change after you do your append, or html, or however you add the element) it will work.

EDIT

As noted in a comment you could also use on. However, on will also require the element to be on the page, unless your target for the on is the body itself (in which case you're basically just using on to do the same thing as live).

machineghost
  • 28,573
  • 26
  • 128
  • 197
  • 1
    `.live()` is deprecated – Samuel Cook Dec 20 '16 at 21:03
  • It is ... and my answer mentions that, discusses the reason for it, and offers an alternative :) – machineghost Dec 20 '16 at 21:10
  • You can do delegation with `.on()`. That's the replacement for `.live()`. – Barmar Dec 20 '16 at 21:33
  • You can, but then you might as well use `live`. You have to understand, just because `on` isn't deprecated doesn't inherently make it any better than `live`, and in fact using `on` to bind to `document.body` is the same thing as using `live`. Both of them achieve "delegation" by binding an event handler to the body, and both share the downside of that approach, which is that every handler you put on the body slows the page down, because every time another (bubbling) event occurs on the page the browser has to check "does this `document.body` handler apply? how about this one? how about ..." – machineghost Dec 20 '16 at 21:35
  • I should add that you can even read the source of jQuery to see as much. The definition of `live` is literally just an `on` call: `live: function( types, data, fn ) { jQuery( this.context ).on( types, this.selector, data, fn ); return this; },` What matters (performance-wise) is whether or not you put event handlers on the body, not which jQuery method you use to do it is. – machineghost Dec 20 '16 at 21:39
0

I found by changing the .change(function(){ to .live('change', function(){ the code is now working.

user2924019
  • 1,581
  • 3
  • 24
  • 44
0

I would suggest giving new ids to new created checkboxes by iterating n and give them a class of checks. lets say you have a function

function createNewBox()
{
    //code that create new boxes with new ids
}

now you use your code like this. You get the id and call that checkbox to perform your function.

$(".class").on('change', function(){
    var id = $(this).attr("id");
    $("#"+id).closest("tr").toggleClass("checked", this.checked);
});
Ali Rasheed
  • 2,629
  • 2
  • 15
  • 24
  • While I think it's a good idea to bind elements by `class` in general, I'm not sure that will help in this case. It sounds like the OP's issue is that they are binding the event handler before the element has been added to the page (or at least that's what I took from "but just not the ones generated with JQuery"). If that's the case, adding an `id` or `class` won't help, because regardless the element won't be there when the event is bound. – machineghost Dec 20 '16 at 21:15
  • Well... it's a good practice to bind a class cuz it would allow him to change the looks or use it for other purpose in future – Ali Rasheed Dec 20 '16 at 23:04