13

I load a form and dynamically populate a select via AJAX from a PHP file. Before implementing the dynamic AJAX populated select, my change function works (it just shows another input when a user selects 'other'). Now the change function does not work.

I know the ready function is firing because the jStepper functions run. I have tried this with the change function in and outside the ready function. I have a feeling the change function loads before the AJAX get is finished, but does that really matter?

var types = "<select name='ve_categoryNo' id='ve_categoryNo'>";
var d = new Date();
$.get('scripts/vehicle_category_feed.php?date=' + d.getTime(), function ($type)
{
    $($type).find('type').each(function ()
    {
        types += "<option value='" + $(this).attr("categoryno") + "'>" + $(this).attr("category") + "</option>";
    });
    types += "<option value='other'>Other(Specify)</option></select>";
    $('#ve_categoryNo_td').html(types);
});
$(document).ready(function ()
{
    $('input[type=text]').click(function ()
    {
        $(this).select();
    });
    $('#vehicle_entry').ajaxForm(function ()
    {
        showMessage('vehicle_information_added');
    });
    $('#ve_ariNo').jStepper({minValue: 1, maxValue: 99999999});
    $('#ve_fleetNo').jStepper({minValue: 1, maxValue: 999999999});
    $('#ve_vehicleYear').jStepper();
    $('#ve_purchasePrice').jStepper({minValue: 0});
    $('#ve_categoryNo').change(function ()
    {
        if ((this.value) == "other")
        {
            $('#otherCategory').show();
            $('#otherCategory input[type=text]').focus();
        } else
        {
            $('#otherCategory').hide();
        }
    });
});
joey8oro
  • 97
  • 1
  • 3
  • 14
ahhchuu
  • 441
  • 2
  • 7
  • 17
  • Possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – showdev Jul 05 '16 at 22:27

3 Answers3

31

modify this:

$('#ve_categoryNo').change(function() { 

to

$(document).on('change', '#ve_categoryNo', function() { 

EDIT3: This would perform the best after an examination of your code more closely:

   $('#ve_categoryNo_td').on('change', '#ve_categoryNo', function() {

as it binds closest to the element in question.


You should also put the ajax call inside the ready script I would think.

The reason this is occuring is that there is nothing in the DOM to bind to when it is instantiated. Using the .on in this manner binds it to the document instead. If you had another "fixed" element that wraps it, it might be better to bind to that using that in place of "document" as it would likely perform better.

EDIT: Note that you COULD also add the change event management after you inject the element as part of the ajax call completion, but if you do this more than once, you should unbind it first in that case.

EDIT2: since there are questions/comments: FROM THE DOCUMENTATION: http://api.jquery.com/on/

Attaching many delegated event handlers near the top of the document tree can degrade performance. Each time the event occurs, jQuery must compare all selectors of all attached events of that type to every element in the path from the event target up to the top of the document. For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • Yes! Brilliant, you fixed it. Could you perhaps explain why it works one way and not the other? – ahhchuu Mar 29 '12 at 16:38
  • 1
    Be careful how many items you bind to $(document) - its a better practice to bind to an element as close to the selector as you can (that isn't replaced by a DOM modification of course) Great answer though. – mikevoermans Mar 29 '12 at 16:44
  • @mikevoermans - exactly why I added the note regarding the closer element and the option to add at injection point. – Mark Schultheiss Mar 29 '12 at 16:46
  • 1
    @Sinan .live binds differently and is slower as a result - it is recommended to use .on in the documentation – Mark Schultheiss Mar 29 '12 at 17:26
  • I added an example of closer binding of the .on for this specific example given the comments. – Mark Schultheiss Mar 29 '12 at 17:41
  • the current doc about .change says: This method is a shortcut for .on( "change", handler ). – Pablo Pazos Jul 04 '15 at 02:02
  • @PabloPazosn - yes and one reason I prefer that "on" syntax. Also due to the ability to add other events without alteration of the original as well as it just "reads" better to me and is clear it is an event handler and not an event trigger. – Mark Schultheiss Jul 08 '15 at 16:33
  • thanks, m facing the same problem. now i got the solution with a proper explanation too. – Pritam Jinal Jan 20 '16 at 06:38
  • Thanks buddy, your solution still solves the problem in 2017 ;) – b1919676 Mar 12 '17 at 10:11
2

I think the element you are binding to in the line:

$('#ve_categoryNo').change(function() { ...

does not yet exist in the DOM, so the event does not get bound.

Try using the .live function:

$('#ve_categoryNo').live('change', function() { ... });

Or make sure that your DOM elements exist before you try to bind events to them.

Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75
  • 1
    the `.on(` syntax is preferred over `.live(` and will perform better, especially if bound closer to the element in question. – Mark Schultheiss Mar 29 '12 at 16:47
  • see the latest example of my answer for binding closer as well as some notes on performance. live always binds to the document is my understanding. – Mark Schultheiss Mar 29 '12 at 17:42
-1

Worked from document ready to change works Ajax functionality

$(document).change(function(){
  $("#next").click(function() {
     var questionid = $('#question').val();         
     var assementid = $('#assement').val();         
     var userid     = $('#user').val();         
     if($('.ansradio').is(':checked')) { 
        var answer = $('input[name=ans]:checked', '#questionajax').val();
        $.ajax({
           type: "POST",
           url: "answer/",
           data: "q_id="+questionid+"&a_id="+assementid+"&answer="+answer+"&user_id="+userid,
           success: function(html){
              $("#questionajax").html(html).show();
           }
        });
     }
     else{
        alert("Please answer the questions");
     }     
  });

});

Vinoth Smart
  • 383
  • 3
  • 13