jaime
jaime

Reputation: 2334

Why is my jquery .on('change') not working for dynamically added selects

I'm adding select elements dynamically, like in the below HTML. I'm not sure why the .on('change' ...) is not working for the dynamic select. What am I missing?

I'm using Chrome 24.0.1312.57 + jquery 1.8.3.

<script type="text/javascript">
  $(document).ready(function() {
      $('#x select').on('change', function () { alert('helo'); })
      $('#y select').on('change', function () { alert('helo'); })

      $('#x').html($('#y').html());
  });
</script>

<div id="x"></div>
<div id="y">
    <select>
        <option>O1</option>
        <option>O2</option>
    </select>
</div>

Upvotes: 26

Views: 75519

Answers (10)

Naxia
Naxia

Reputation: 9

Came across this as I could not get my dynamically created selects which came back from an ajax post with dynamic id's, to trigger the event.

$(document).on('change', 'select', function (e) {
    $("#theDiv select").on("change",function(){ post("SelectChanged");} );
});

This would not work until I had changed something first so I added

$("#theDiv select").on("change",function(){ post("SelectChanged");} );

However this not meant, that after the change, all other changes then fired twice. This may not be very good practice. But what I did was to to put in a function that is called at the start and each return of ajax.

 `function myFuncs(){
    $('#theDiv select').unbind('change');
    $('#theDiv select').on('change' function(){ post('selectChanged'); });
  }`

But had to unbind at start of each function call else it doubled up the functions each time. I am sure there must be a proper way to do this, I just haven't found it yet. Thanks for starting the question.

Upvotes: 0

user889030
user889030

Reputation: 4754

Don't use .live()/.bind()/.delegate(), though. You should use .on().

for both static and dynamic select changes

$(document).on('change', 'select', function (e) {
    // do something 
});

Upvotes: 8

Dominic
Dominic

Reputation: 31

The word in square brackets is the alt text, which gets displayed if the browser can't show the image. Be sure to include meaningful alt text for screen-reading software.

Upvotes: 1

Dominic
Dominic

Reputation: 31

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

        $('#tablecontent').on('change', 'table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

Upvotes: 1

VickenCode
VickenCode

Reputation: 305

This is easy. Whatever class or id your targeting, try being more precise but no need to include a super parent.

Example of wrong way:

        $('#tablecontent').on('change', '#tablecontent > table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

CORRECT WAY:

        $('#tablecontent').on('change', 'table.CampaignGrid > tbody > tr > td', function(e) {
            console.log('IN TABLE CONTENT CHANGE');
            var value = e.target.value;
            $('button#updateLuck').prop('disabled', false).css({'color': '#000', 'font-weight': 600});

            //alert($(ele[0]).html());
        });

Notice I dropped the super parent: '#tablecontent'

It all about clarity.

  • V

Upvotes: 1

cernunnos
cernunnos

Reputation: 2806

Your code:

$('#x select').on('change', function () { alert('helo'); })

attaches an event handler to the select inside the #x element.

What you want (from what i understood) is something in the lines of:

$("#y").on('change','select',function () { alert('helo'); });

This attaches an event handler to the #y element that gets delegated to its children 'select' elements

From http://api.jquery.com/on/

The .on() method attaches event handlers to the currently selected set of elements in the jQuery object.

Upvotes: 41

jamesbat.es
jamesbat.es

Reputation: 53

The whole point of .on() is so that you can bind the event to something other than the document. This is what the now depreciated .live() did and it is inefficient in most cases. You are ment to bind the event to the closest parent element that will not be dynamically changed.

As far as I am aware this is the correct syntax:

$('#x').on('change', 'select', function(){
    alert('hello');
});

If #x or #y will be changed, wrap them on an element and bind the event to that.

Upvotes: 1

d_ethier
d_ethier

Reputation: 3911

Event binding to elements that are not in the DOM on initial page load will not work. You need to bind to an element further up the DOM that exists to allow the event to trickle down. This is usually the approach that I take:

$(document).on({
  change: function() {
    alert('helo');
  }
}, '#x select');

$(document).on({
  change: function() {
    alert('helo');
  }
}, '#y select');

I prefer it as you can add subsequent events easily.

$(document).on({
  change: function() {
    alert('helo');
  },
  blur: function() {
    alert('helo');
  }
}, '#x select');

Upvotes: 14

CodeChimp
CodeChimp

Reputation: 8154

Your event binding is set on $(document).ready(). However, if you are dynamically adding them later (like via jQuery.appendTo() or the like), the newly added components need to be binded since they were not part of the inital one that happened in $(document).ready(), which only runs once when the page is loaded and the DOM is initially done.

Upvotes: 3

thecodeparadox
thecodeparadox

Reputation: 87073

Correct syntax:

 $('#x').on(
        'change', 
         'select', 
          function () { 
            alert('helo'); 
          }
       );

So syntax of on() for dynamic element seems:

$(staticParent).on( eventName, target, handler);

Upvotes: 1

Related Questions