Reputation: 2334
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
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
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
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
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
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.
Upvotes: 1
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
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
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
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
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