jQuery .on('change', function() {} not triggering for dynamically created inputs - javascript

The problem is that I have some dynamically created sets of input tags and I also have a function that is meant to trigger any time an input value is changed.
$('input').on('change', function() {
// Does some stuff and logs the event to the console
});
However the .on('change') is not triggering for any dynamically created inputs, only for items that were present when the page was loaded. Unfortunately this leaves me in a bit of a bind as .on is meant to be the replacement for .live() and .delegate() all of which are wrappers for .bind() :/
Has anyone else had this problem or know of a solution?

You should provide a selector to the on function:
$(document).on('change', 'input', function() {
// Does some stuff and logs the event to the console
});
In that case, it will work as you expected. Also, it is better to specify some element instead of document.
Read this article for better understanding: http://elijahmanor.com/differences-between-jquery-bind-vs-live-vs-delegate-vs-on/

You can use any one of several approaches:
$("#Input_Id").change(function(){ // 1st way
// do your code here
// Use this when your element is already rendered
});
$("#Input_Id").on('change', function(){ // 2nd way
// do your code here
// This will specifically call onChange of your element
});
$("body").on('change', '#Input_Id', function(){ // 3rd way
// do your code here
// It will filter the element "Input_Id" from the "body" and apply "onChange effect" on it
});

Use this
$('body').on('change', '#id', function() {
// Action goes here.
});

Just to clarify some potential confusion.
This only works when an element is present on DOM load:
$("#target").change(function(){
//does some stuff;
});
When an element is dynamically loaded in later you can use:
$(".parent-element").on('change', '#target', function(){
//does some stuff;
});

$("#id").change(function(){
//does some stuff;
});

you can use:
$('body').ready(function(){
$(document).on('change', '#elemID', function(){
// do something
});
});
It works with me.

You can use 'input' event, that occurs when an element gets user input.
$(document).on('input', '#input_id', function() {
// this will fire all possible change actions
});
documentation from w3

$(document).on('change', '#id', aFunc);
function aFunc() {
// code here...
}

Related

JQuery on change event firing for the wrong element

I have two <select> elements: select.exerciseType and #moduleTopic, each with their own handler wrapped around the document. I believe it's important to know that select.exerciseType is dinamic and there can be multiple of those.
Their events are:
$(document).ready(function() {
$(document).on("change", $("select.exerciseType"), function(e) {
<!--Code not really important-->
}
$(document).on("change", $("#moduleTopic"), function(e) {
<!--Code not really important-->
}
}
My problem is, when I change the selected option in one of those selects, both those events are firing. Why is the selector in the on() function not working and how can I make it work?
Syntax for jQuery .on handler is .on( events [, selector ] [, data ], handler ) where second argument is string
In your case, as it is not string, it is omitted and the event is always triggered when it reaches the selected element!
$(document).ready(function() {
$(document).on("change", "select.exerciseType", function(e) {});
$(document).on("change", "#moduleTopic", function(e) {});
});
Can you use this code instead:
$("#moduleTopic").change(function() {
// code executes here
});
EDIT ---
You can use a classname and detect the <select> being changed by the use of $(this) inside your function.
You don't need document.ready and you also just specify the selector, not retrieve it. i.e.
// class example
$(document).on("change", "select.exerciseType", function(e) {
// Code not really important
});
// ID example
$(document).on("change", "#moduleTopic", function(e) {
// Code not really important
});

jQuery unbind after first click

This causes multiple buttons to take action:
$(document).on("click", ".file-this-email", fileThisEmail);
When fileThisEmail runs, I'd like to remove it from ONLY the current one (there are others on the page that still need it):
window.fileThisEmail = function(e) {
console.log('this was clicked');
}
I tried off, but couldn't seem to get it right. Any ideas?
In this case, you have to make the current element no longer match the ".file-this-email" selector.
$(document).on("click", ".file-this-email", function() {
console.log('this was clicked');
$(this).removeClass("file-this-email");
});
An alternative would be to add a filter to the selector, with the same concept.
$(document).on("click", ".file-this-email:not(.clicked)", function() {
console.log('this was clicked');
$(this).addClass("clicked");
});
Or, don't use delegation for this particular case. Delegation isn't some new technology that replaces direct binding, it's just another way of binding events. If used correctly, it can make code more efficient. The opposite is true too; if used incorrectly, it can make the code very bloated.
$(".file-this-email").on("click", function () {
console.log("this was clicked");
$(this).off("click");
});
// or even better (thanks #overachiever):
$(".file-this-email").one("click", function () {
console.log("this was clicked");
});
Bind individual handlers to each element like this:
$(".file-this-email").one("click",fileThisEmail);
What you should do is
$(document).on("click", ".file-this-email", fileThisEmail);
change this to
$(document).ready(function(){
$(".file-this-email").on("click",fileThisEmail);
$(".file-this-email").click(function(){
$(this).off("click",fileThisEmail);
});
});
The .one() method is good for this. http://api.jquery.com/one/
$(document).ready(function(){
$('.file-this-email').one('click', fileThisEmail);
});

Single .on click for multiple elements

I have the following jquery...
$(".parentElem").on("click", "input[id*='myitem']", function() {
myfunction();
});
and
$(".parentElem").on("click", "input[id*='myotheritem']", function() {
myfunction();
});
These both work fine, but I don't want to have to list every clickable element separately... I'd much rather list them all at once - something like this...
$(".parentElem").on("click", "input[id*='myitem'], input[id*='myotheritem']", function() {
myfunction();
});
Is this possible? It doesn't seem to work for me.
The second argument in the .on() method is a CSS selector. So you don't have to pass in each individual element with their ID. You could just use a generic class or selector like this:
$('.parentElem').on('click', 'input', function(event) {
// Function body here
});
Simply don't use the delegation feature, instead do your own checking:
$(".parentElem").on("click", function() {
// check if event.target matches an element that you want to trigger on
});
This works for me:
$(".parentElem").find("input[id*='myitem'], input[id*='myotheritem']").each(function(){
$(this).click(function(){
myfunction();
});
});
DEMO

Image not clickable after loaded via AJAX

I have a set of images that are loaded via jQuery AJAX. For some reason, my click handler won't trigger when it is clicked.
JavaScript:
$(document).ready(function()
{
$('img.delete_related_sub').click(function()
{
alert('testing');
});
//I added this part to test, because the above wasn't working...
$(document).click(function(event)
{
alert(event.target.tagName+' '+event.target.className);
});
});
HTML:
<img data-rsid="2" class="delete_related_sub" src="image.png" />
So my 2nd click handler alerts me with "IMG delete_related_sub". But the first one isn't triggered. The is actually in a table that is actually in a pane run by bootstrap tabs, not sure if that'd actually help though.
Try it like this
$(document).on('click', 'img.delete_related_sub', function() {
alert('testing');
});
Just replace document with a static parent of your image.
Use this:
$("body").on('click', 'img.delete_related_sub', function() {
alert('testing');
});
Or, in the success: give this:
$('img.delete_related_sub').click(function() {
alert('testing');
});
Because the line to bind the event runs before the element is added, try using
$(parent).on('click', 'img.delete_related_sub', function() {});
where the parent is a static element that will be there for sure. This works because the event is bound to an element that actually exists, then checks to match your selector. See .on() for more details.
Something like
$(document).on('click', 'img.delete_related_sub', function() {});
would work fine.
$('.delete_related_sub').live("click", function()
{
alert('testing');
});
Use live event to listen clicks

Attach an event immediately after setting up the HTML content

This is an example of my jQuery code that I use in a function to do pagination:
// new_content is a variable that holds the html I want to add to a div
$('div#my_div').html(new_content);
$("div#my_div a.details").hover(function(){
$(this).fadeIn(); //code to execute when the mouse get in
}, function(){
$(this).fadeOut(); //code to execute when the mouse get out
});
BUT the hover event does not work at all, and I believe that this is caused because the DOM is not ready yet!
To get around this I used set up a timer like this:
$('div#my_div').html(new_content);
window.setTimeout(
$("div#my_div a.details").hover(function(){
$(this).fadeIn(); //code to execute when the mouse get in
}, function(){
$(this).fadeOut(); //code to execute when the mouse get out
});
,100);
I asked this question because I'm sure that this is not the right way to attach an event immediately after the html method (maybe it didn't it's work!).
si I hope someone show me the right way to do it.
You would want to use the live mouseover mouseleave events
$("div#my_div").live({
mouseenter: function()
{
},
mouseleave: function()
{
}
}
);
Alternately you could do:
$('div#my_div').live('mouseover mouseout', function(event) {
if (event.type == 'mouseover') {
// do something on mouseover
} else {
// do something on mouseout
}
});
UPDATE
In newer versions of jQuery you can do it like this
$('body').on('mouseover','#my_div', function(){});
$('body').on('mouseout', '#my_div', function(){});
Maybe you need to use the live() method. As you can read here, it seems that you will need to separate the two events:
.live("mouseenter", function() {...})
.live("mouseleave", function() {...});
UPDATE: Someone voted me up, so if someone gets here, I recommend to read the on() documentation (here) as live was deprecated long ago. Also, it may be interesting to see mouseenter()(link) and mouseleave() (link). The idea is the same as with live.
It is better to use a delegate rather than live, as live is essentially a delegate on the document.body causing it to have to bubble much longer.
Here is an example using a delegate: http://jsfiddle.net/Akkuma/wLDpT/
you can check out .live function of jquery. Here is the link
http://api.jquery.com/live/

Categories

Resources