0

I have the following code (playing with some selects).

After the first change function, the second change function does not work:

        jQuery('.toPopSelect').change(function(){
            console.log("hey");
        });  

I think it's because the first change function replaces some html and jQuery can't select the .toPopSelect class after.

Any idea why is this happening? is there a way around it?

    <select class="theSelect">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
    </select>

    <div class="toPopulate">
        <select class="toPopSelect">
            <option value="1">1</option>
            <option value="2">2</option>
        </select>
    </div>




jQuery(document).ready(function(){

        jQuery('.theSelect').change(function(){
            jQtoPopulate = jQuery('.toPopulate');
            jQtoPopulate.empty();
            jQtoPopSelect = jQuery('.toPopSelect');
            v = jQuery(this).val();

            if ( v == 1) {
                console.log("ues")
                jQtoPopulate.html('<input type="text" size="60"><\/input>');
            } else {
                jQtoPopulate.html('<select class="toPopSelect"><option value="1">1<\/option><option value="2">2<\/option><option value="3">3<\/option><option value="4">4<\/option><option value="5">5<\/option><\/select>');

                jQtoPopSelect.append('<option value="6">6<\/option>');
            }

        });

        jQuery('.toPopSelect').change(function(){
            console.log("hey");
        });

    });

Any ideas?

Dany D
  • 1,189
  • 2
  • 18
  • 44
  • Great explanation here also... http://stackoverflow.com/questions/9995638/what-is-best-way-to-perform-jquery-change – Dany D Sep 26 '13 at 15:51

4 Answers4

2

You must use a listener like this because you add code after.

The jsFiddle to illustrate that : http://jsfiddle.net/s6MVQ/

$(document).on('change', '.toPopSelect', function(){
    alert("ok");
});

More information on : http://api.jquery.com/on/

Donovan Charpin
  • 3,567
  • 22
  • 30
1

You have to do event delegation properly. Since .toPopSelect is created dynamically, you have to handle event in the following way. jquery .on() documentation

$(document).on('change', '.toPopSelect', function(){
    console.log("hey");
}); 

Even better (for performance) if you could replace document with a static outer container's class/id

Venkata Krishna
  • 14,926
  • 5
  • 42
  • 56
  • I've felt that BYossarian is more complete, this is why I have selected his answer as the accepted one. I have up voted your answer – Dany D Sep 26 '13 at 16:15
0

try this:

jQuery(document).ready(function(){

        jQuery('.theSelect').change(function(){
            jQtoPopulate = jQuery('.toPopulate');
            jQtoPopulate.empty();
            jQtoPopSelect = jQuery('.toPopSelect');
            v = jQuery(this).val();

            if ( v == 1) {
                console.log("ues")
                jQtoPopulate.html('<input type="text" size="60"><\/input>');
            } else {
                jQtoPopulate.html('<select class="toPopSelect"><option value="1">1<\/option><option value="2">2<\/option><option value="3">3<\/option><option value="4">4<\/option><option value="5">5<\/option><\/select>');

                jQtoPopSelect.append('<option value="6">6<\/option>');
            }

        });

        var c = $(document);
        c.delegate(".toPopSelect","change",function(){ alert("hey"); });

    });
Hugo Tostes
  • 412
  • 4
  • 13
0

It's as you say. Because you're changing the DOM when you change the first select element, it's writing over the second select element, and therefore the element to which your console.log("hey"); event handler is attached no longer exists.

When your code runs this:

jQuery('.toPopSelect').change(function(){
            console.log("hey");
});

what it's doing is attaching the handler to all elements that match .toPopSelect at the time that the code is run. It isn't attaching an event handler to all and every .toPopSelect that will ever occur within your page.

Therefore you can reattach the event handler after changing the DOM:

jQuery('.theSelect').change(function(){
    // stuff that changes DOM here

    jQuery('.toPopSelect').change(function(){
        console.log("hey");
    });
});

Another thing you can do is use:

$('.toPopulate').on('change', '.toPopSelect', function(){
    console.log("hey");
});

This assigns an event handler to .toPopulate but will only be trigger by events matching the second argument (.toPopSelect). See: http://api.jquery.com/on/

Note that if you change or remove .toPopulate from the DOM then this will also no longer apply. (Basically choose the nearest ancestor of .toPopSelect that will remain within the DOM.)

Ben Jackson
  • 11,722
  • 6
  • 32
  • 42
  • Great explanation, but won't the reattachment take place each time the first change event happens? I belive Krishna's solution would be more efficient. Wouldn't you agree? – Dany D Sep 26 '13 at 15:48
  • yeah, i included both solutions just to cover all the bases. As to which is more efficient, that depends on a bunch of factors but in a lot of cases I imagine that the difference isn't worth worrying about. Personally, I would go with attaching the event once to `.toPopulate`, then you don't have to worry about it so much. – Ben Jackson Sep 26 '13 at 15:55
  • I've selected your question as the accepted answer since the explanations are complete. – Dany D Sep 26 '13 at 16:04