25

Using .load, I'm loading the following content into #step_2 div:

<div id="step_2">
    Select a subcategory:
    <select id="subcategory_id" name="subcategory_id">
        <option value="0">All subcategories</option>
        <option value="68">Cool</option>
        <option value="15">Cooler</option>
        <option value="74">Excellent</option>
    </select>
</div>

I'm then trying to detect when user selects something:

$("#subcategory_id").on("change", function(){
    alert( 'Success!' );
});

but with no success. Does anyone see what I'm doing wrong? Help greatly appreciated.

NOTES:

Here's the full CSS path as seen by FireBug:

html.js body div#container div#main form div#step_2 select#subcategory_id

Here's the full Javascript file, if context matters:

$(document).ready(function() {

    $("#category_id").change(function() {
        $("#spinner").show();
        $("#step_2").load("process.php?selected=category", { value: $(this).val() }, function() {
            // Do something to say the data has loaded sucessfully
            $("#spinner").hide();
        });
    });
            
    $("#subcategory_id").on("change", function(){
        alert( 'Success!' );
    });
    
});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
CodeVirtuoso
  • 6,318
  • 12
  • 46
  • 62

5 Answers5

38

In this case you need to use on in a similar way to delegate, the syntax you are using is the replacement for bind.

$("#step_2").on("change", "#subcategory_id", function(){
    alert( 'Success!' );
});

The first selector has to be an element that won't be replaced. This way, when the event bubbles up to this point it is caught. You then specify the actual element that will trigger the event as the 2nd parameter of .on.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Richard Dalton
  • 35,513
  • 6
  • 73
  • 91
  • There's been a few identical correct answers, but I've chosen this one because of best explanation. Thanks @Richard D, as well as everyone else. – CodeVirtuoso Dec 01 '11 at 16:24
14

on(...) won't subscribe to events that aren't on the page yet without the proper setup. To do what you want, you should try the following:

$(document).on("change", "#subcategory_id", function(){
    alert( 'Success!' );
});

To make this more efficient, you should replace $(document) with the closest parent of the element that you know will be on the page when this code is called.

Dan Herbert
  • 99,428
  • 48
  • 189
  • 219
5

You have to bind the handler after you've loaded the html, or use

$("#step_2").on("change", "#subcategory_id", function(){
    alert( 'Success!' );
});
Tetaxa
  • 4,375
  • 1
  • 19
  • 25
5

Sure it can,

$(document).on("change", "#subcategory_id", function(){...});

To delegate events using .on, provide a parent element to bind to, and then the selector to delegate to.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
2

You have to set the event after that you have loaded the new element. As AJAX is asynchronous, you need to have a callback in your load.

$(document).ready(function() {

    $("#category_id").change(function() {
        $("#spinner").show();
        $("#step_2").load("process.php?selected=category", { value: $(this).val() }, 
        function() {
        // Do something to say the data has loaded sucessfully
            $("#spinner").hide();

            $("#subcategory_id").on("change", function(){
                alert( 'Success!' );
            });

        });
    });

});
jValdron
  • 3,408
  • 1
  • 28
  • 44