This question already has answers here:
Event handler not working on dynamic content [duplicate]
(2 answers)
Events triggered by dynamically generated element are not captured by event handler
(5 answers)
Closed 9 years ago.
I have a <select class="listenToMe" /> that when changes does something. I also have a separate link that when clicked performs an ajax request and returns more dom elements and inside them it has another <select class="listenToMe" />
I would like my event listener to be applied to this element as well. I am trying to use jQuery's on method but it doesn't appear to be working:
JS
var selectListener = function() { alert('you change me!'};
$('.listenToMe').on("change", selectListener);
$('.addMore').click( function() {
$.post('myWebPage.php', {} , (function(data) {
$(this).before(data);
// data is something like <div><select class="listenToMe" /></div>
}).bind(this));
});
HTML
<div>
<div>
<select class="listenToMe" />
</div>
<div>
<select class="listenToMe" />
</div>
<a class="addMore">Click me</a>
</div>
Any suggestions?
You can try
$(document).on('change', '.listenToMe', function(){
// Your code here
})
Your using on like live. The difference is subtle but important. You attach on to a static element in your markup and then filter the event based on a selector. This way the on event never goes out of scope, e.g. if I have the markup
<!-- this div is not dynamically loaded-->
<div id="mystaticDiv">
<!--insert dynamic content here-->
</div>
which when I add my dynamic markup will become:
<!-- this div is not dynamically loaded-->
<div id="mystaticDiv">
<!--insert dynamic content here-->
<div class="myDynamicdiv></div>
</div>
To fire an event on the click of my dynamic div that never needs rebinding I would write the following jQuery:
$('#mystaticDiv').on('click', '.myDynamicdiv', function() {/*Do stuff*/});
So I'm binding my on to the #mystaticDiv but filtering on .myDynamicdiv. Now I can add as many .myDynamicdivs as I want and this will work.
I mentioned live. This is deprecated but works in the same way as you were attempting. This attaches an event to the document of the page with a selector base on the selector your attaching live to. So $('.myDynamicdiv').live('click', function() {/*Do stuff*/}); is directly equivalent to $(document).on('click', '.myDynamicdiv', function() {/*Do stuff*/});. the reason I mention this is this is how you were trying to use on.
Your code $('.listenToMe').on("change", selectListener);. Will not work for dynamic content. This code attaches the event to the dynamic content, that doesn't exist yet. So the is never actually bound. Interestingly $('.listenToMe').on("change", selectListener); is exactly what $('.listenToMe').change(selectListener); does under the hood.
Related
I have a html form which contains a button. This button has a .click() event attached within a js file. This was working fine, until I used jquery .html() to substitute my main page content with the form content. The form shows on the page but clicking the button no longer triggers the event. I am wondering why this is? Code below...
html:
<body>
<div id="mainContent">
<!-- Visible page content will show here -->
</div>
<div id="otherScreens">
<form id="loginForm">
<label for="email">Email</label>
<input type="text" id="email" spellcheck="false">
<label for="password">Password</label>
<input type="password" id="password">
<button type="submit" id="signInBtn">Sign In</button>
<ul id="signInMessages"></ul>
</form>
</div>
css:
#otherScreens {
display: none;
}
js:
const mainContentArea = $(document).find('#mainContent');
let onPageContent = $(document).find('#loginForm').html();
$(document).ready(function () {
mainContentArea.html(onPageContent);
});
$('#signInBtn').click(function (event) {
event.preventDefault();
console.log("Hello world!");
}
I tested changing the .click() event to target #mainContent and it triggered upon clicking anywhere within the div on the webpage, as expected. So I'm not quite sure what's happening with the form button?
(does not seem to relate to suggested duplicate Q)
Just put your click function in document.ready(function()
Please check below full jQuery code and replace it with your current code:
const mainContentArea = $(document).find('#mainContent');
let onPageContent = $(document).find('#loginForm').html();
$(document).ready(function () {
mainContentArea.html(onPageContent);
$('#signInBtn').click(function (event) {
event.preventDefault();
console.log("Hello world!");
});
});
Thanks.
This is quite logical (and can be explained). You create an object, wire events to that object - then replace that object with a similar object and you expect the events to magically be wired.. That doesn't happen.
Each time you dynamically add (delete, replace, whatever) elements with events bound to that element, you need the DOM to be aware of that event. Even so, you could even end-up having more than one event wired to the same element.
So let's say (as an example).
function replaceElement(htmlContent) {
$('.mybutton').off('click'); // drop the event handler
$('#mainContent').html(htmlContent); // replace content
// add event handler
$('.mybutton').click(function() {
console.log('yup, working again');
});
}
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 2 years ago.
I am having a input of type = " file " on my page. Also I have a button "Add Inputs" on the page which adds a new file input element on page and I want to run a function when user changes the value of any of those inputs by selecting a new file.
Here is my code.
HTML
<div class="main">
<div id="InpDiv">
<input type="file" name="fname">
</div>
</div>
<div>
<button onclick="addInp()">Add Inputs</button>
</div>
JS
// Function that is going to run after change in file input.
$(document).ready(function(){
$("input[name='fname']").each(function(){
$(this).change(function(){
alert('hello');
// Do some work here.
});
});
});
// Function that adds new file inputs.
function addInp()
{
$('#InpDiv').clone().appendTo(".main");
}
Now the problem is .change() method works fine for those inputs which were present already on page but not works (won't prompt "hello" message here) on change of values in those newly created inputs. I made more than one file inputs already present on page and .change() worked for all of them but it didn't worked for any of the newly created inputs.
Is it so that events won't work with dynamically added elements on page ?
And if so then how am I going to get this work done?
Try delegation approach using .on(). This will ensure that events will be attached to all the elements that are added to the DOM at a later time.
Also I will prefer using input event instead of change:
Change:
$(this).change(function(){
To:
$('.main').on('input', this, function(){
$(document).ready(function(){
$("input[name='fname']").each(function(){
$('.main').on('input', this, function(){
alert('hello');
// Do some work here.
});
});
});
// Function that adds new file inputs.
function addInp()
{
$('#InpDiv').clone().appendTo(".main");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<div id="InpDiv">
<input type="file" name="fname">
</div>
</div>
<div>
<button onclick="addInp()">Add Inputs</button>
</div>
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 6 years ago.
I'm trying to create a form that allows user to edit the input through new window. PHP will process the input then append the new input with the new values. Apparently, when I try to edit the appended input, the JavaScript just won't fire. Please enlighten me on what I did wrong.
This is my html code:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('.races').click(function(e){
console.log("Inside Testing");
e.preventDefault();
var currID = this.id;
var content = '<form id="theForm" action="ct.php" method="post"> Race: <input type="text" id="race" name="race"><button type="submit" onClick="OKClicked()">Click this!</button></form>';
childWin = window.open('', "_blank", "height=400, width=550, status=yes, toolbar=no, menubar=no, location=no,addressbar=no");
toBeAdded = $(this).closest('div');
childWin.document.close();
childWin.document.write(content);
popupRace = childWin.document.getElementById("race");
parentRace = document.getElementById(currID);
transferValues();
})
});
function transferValues()
{
popupRace.value = parentRace.value;
}
function setValue(text)
{
childWin.close();
toBeAdded.parent().append(text);
toBeAdded.remove();
}
</script>
</head>
<body>
<div>
Name: <input type="text" name="name">
</div>
<div>
<div>
<input type="hidden" name="race-0" value="Human" id="race-0">
<span>race: Human</span>
Edit
</div>
</div>
<div>
Name: <input type="text" name="name">
</div>
<div>
<div>
<input type="hidden" name="race-1" value="God" id="race-1">
<span>race: God</span>
Edit
</div>
</div>
</body>
</html>
And this is my php code:
<?php
$postDataKey = array_keys($_POST);
$text = "";
foreach ( $postDataKey as $currPostKey )
{
$currValue = $_POST[$currPostKey];
$text .= '<div><input type="hidden" name="'.$currPostKey.'-1" value="'.$currValue.'" id="'.$currPostKey.'-1"><span>'.$currPostKey.': '.$currValue.'</span> Edit</div>';
}
echo
'
<html>
<head>
<script>
window.opener.setValue(\''.$text.'\');
</script>
</head>
</html>
'
;
?>
jQuery is only aware of the elements in the page at the time that it runs, so new elements added to the DOM are unrecognized by jQuery. To combat that use event delegation, bubbling events from newly added items up to a point in the DOM that was there when jQuery ran on page load. Many people use document as the place to catch the bubbled event, but it isn't necessary to go that high up the DOM tree. Ideally you should delegate to the nearest parent that exists at the time of page load.
You will likely want to change event handlers so they use the on() method.
This was solved in older versions of jQuery with the live function, opposed to the bindfunction.
The bind function attached an event to all the matching elements, as long as they existed in the moment of execution. Any element appended afterwards would be excluded.
The livefunciton would attach the event on any matching element, even if the element was created after the execution of the instruction.
On the present version of jQuery, bind and live has been replaced by on. The default behavior of on()is like bind. Fortunately there is a way to use on so that it works like live.
I wrote an article about it, which it may help you understand how.
To sum it up...
// This behaves like `bind`
$(".clickable").on("click", function(){...});
// This behaves like `live`
$(".parent-element").on("click", ".clickable", function(){...});
So just search the common parent element that all possible elements could possibly have (you could use $(document) if you do not want to think too hard) and you are golden.
jQuery on Method is what you're looking for; click the link and look for delegated events.
"Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. "
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 years ago.
jQuery does not seem to be able to select a loaded HTML element. Here is my HTML:
<div class="class name" style="display: none;">
<div id="submenuID" class="submenuID" />
<script>
loadHtmlUsingJavascript('parameter1', 'parameter2');
</script>
</div>
The loaded HTML is a list of links. This is my JavaScript:
$("#submenuID li").addClass("active");
But it would not add the class. After some snooping around. I learn to use
$("#submenuID li").live('click', function() {
$("#submenuID li").addClass("active");
});
However, it does not work until I click on the link a second time.
You have to do the following:
$("#submenuID").on('click', 'li', function() {
$(this).addClass("active");
});
First, the jQuery .live function is deprecated since jQuery 1.7 (http://api.jquery.com/live/)
Also, you should be listening for li methods inside the #subMenuID element.
I have a page called forms.php with a javascript included in its head and a div called fadeinContents
i used Ajax to load part of a file called #sections1 into this div which works quite well
But i need to execute some Jquery on the loaded contents in the fadeinContents when they are clicked. Ive read other post but couldn't understand them well..
Here are my files
forms.php
<html>
<head>
<script type="text/javascript" src="scripts/scripts.js"></script>
<script type="text/javascript" src="scripts/login.js"></script>
</head>
<body>
<div class="login_link">login</div>
<div class="signup_link">signup</div>
<div class="fadeinContents">
<!--Loaded contents goes here -->
</div>
</html>
Here's my Jquery
$(document).ready(function(e) {
$('#fadeinContents').load('forms.php #sections1');
$('.login_link').click(function(e) {
$('#fadeinContents').load('forms.php #sections1');
});
$('.signup_link').click(function(e) {
$('#fadeinContents').load('forms.php #sections2');
});
$('.recoverPassword').click(function(e) {
$('#fadeinContents').load('forms.php #sections3');
});
});
Loaded File containing
<div class="sections1">
<div class="signup">
<!-- Signup Forms Here -->
</div>
</div>
<div class="sections2">
<div class="login">
<!-- loginForms Here -->
</div>
</div>
<div class="sections3">
<div class="recoverPassword">
<!-- recover form Here -->
</div>
</div>
My problem is that the Recover password click function is not working because it was loaded, Please how can i make this work?
thnx in advance..
then you should bind that event differently. try it like this
$('.fadeinContents').delegate('.login_link', 'click', function(e) {
$('#fadeinContents').load('forms.php #sections3');
});
and so on for the rest of them.
This means that the click event is binded on the .fadeinContents but when triggered, it checks if the target is a .login_link and if so it will triggers the given callback. So delegating the event handler to a higher node will ensure that no matter when the content of the node will load/change or how many elements you have, if they match the criteria the event handler will trigger.
Delegating events is a bit more memory efficient as well. If you have for example one hundred cells you want to add click events to, doing a $(".cell").click( will attach a event listener on every one of them. Delegating it to the body for example with $("body").delegate('.cell', 'click', will only attach one event (and then do some looping and checking there, that's true) but you'll end up with only one event listener and it won't matter how many nodes you later add or remove. they will trigger that click event