Click event on dynamic elements not working - javascript

In framework7, how to add click event on dynamic elements?
If I add my element first on my view, the click event works fine like below:
<div class="test">Click Me</div>
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
But if I have dynamic elements, especially elements dynamically added to virtual-list, I cannot make the click event to work. What is the right way to do this?
I even tried inline function, ex: <div class="test" onclick="myFunction();">Click Me</div>, still this won't work.

You can use:
// Live/delegated event handler
$$(document).on('click', 'a', function (e) {
console.log('link clicked');
});
For your case:
$$(document).on('click', '.test', function(e){
console.log('Some code...');
});
Here is docs. Scroll until events section.

Use this for dinamically added elements:
$$(document).on('click', '.test', function () {
myApp.alert("Gotcha!");
});

All answers are good to go with. But if you are using this class 'test' for other elements of the page, you will end up firing some extra click event(when you click on any other element of same class). So if you wanna prevent that, you should add listener to that particular element.
if you're adding an element of class test to an existing element of id testId, then use
$('#testId').on('click', '.test', function(this){
}

In the function where you dynamically add the new elements you have to assign an event handler for them.
Lets say you have a function something like this
function addNewLines(){
//add the new lines here
// you have to run this again
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
}

Related

How to wrap multiple dynamic eventListeners into one?

I just started to learn js and need a little help: I have the following function:
//SET CHAT BEHAVIOR
function chatSettings() {
console.log('ChatSettings called')
function BtnAndScrollBar(texteditor) {
console.log('BTNAndScrollBar called');
const sendBtn = $('.cl.active').find('.sendBtn');
const attachBtn = $('.cl.active').find('.attachBtn');
console.log(sendBtn)
}
function sendAndDeleteMessage(send) {
console.log(send);
}
var sendBtn = $('.cl.active').find('.sendBtn');
sendBtn.mousedown(function () {
sendAndDeleteMessage(this);
});
var textEditor1 = $('.cl.active').find('.chatTextarea');
textEditor1.on('focus change mousedown mouseout keyup mouseup', function (){
console.log(this);
BtnAndScrollBar(this)
});
}
$('document').ready(function () {
console.log('hello');
$('.tabs').tabs();
chatSettings();
});
I prepared a js.fiddle - As you can see from console.log when clicking into the textarea, the eventListener always listens to #cl1, even if .cl.active switches along with the according TAB.
The events in the textarea are just relevant, if .cl is active. My target is to wrap all three eventListener into one and apply the event to the textarea in the active stream, but all I tried went wrong... Can anyone help? #Dontrepeatyourself #DRY
$(".chatTextarea").on(
'focus change mousedown mouseout keyup mouseup',
function (this) {
//this.id can contain the unique id
greatFunction(this);
});
This will bind event individually with unique id found with this keyword and also wraps all event listener into one function but this is better when you want to process each event with same functionality
please let me know if this helps.
Peace
$(".cl textarea").on('focus change mousedown mouseout keyup mouseup', function () {
greatFunction(this)
});
Tada!
P.S. Is there a reason greatFunction is defined inside window.onload?
Try using $(document).ready function to load code when the page loads.
Also use $('textarea #cl1').on to get the textarea with the #cl1 or whichever id you want to use and then call the function after using the .on.
Hope this helps!
Let me know if it works!
$(document).ready(function () {
function greatFunction(elem) {
//do stuff
}
$('textarea').on('focus change mousedown mouseout keyup mouseup', function () {
greatFunction(this)
});
}
First off, I changed the onload to bind with jQuery, so all your logic is doing jQuery bindings, rather than swapping back and forth between jQuery and vanilla javascript. Also, doing an actual binding removes an inline binding.
Next, the binding has been condensed into a single delegate event listener. Since you eluded in your comments that it wasn't working for the active element after the active was moved or added, this reflected that you were dealing with dynamic elements. Delegate event listeners are one way to handle such things.
Delegate event listeners bind on a parent element of the elements that will change, or be created. It then waits for an event to happen on one of it's children. When it gets an event it is listening for, it then checks to see if the element that it originated from matches the child selector (second argument) for the listener. If it does match, it will then process the event for the child element.
Lastly, I added some buttons to swap around the active class, so you could see in the snippet that the event handler will start working for any element that you make active, regardless of it starting out that way.
$(window).on('load', function () {
function greatFunction (elem) {
console.log(elem.value);
}
$(document.body).on(
'focus change mousedown mouseout keyup mouseup',
'.cl.active .chatTextarea',
function () {
greatFunction(this);
}
);
$('.makeActive').on('click', function () {
$('.active').removeClass('active');
$(this).closest('div').addClass('active');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cl1" class="cl active"><textarea class="chatTextarea">aa</textarea><button class="makeActive">Make Active</button></div>
<div id="cl2" class="cl"><textarea class="chatTextarea">bb</textarea><button class="makeActive">Make Active</button></div>
<div id="cl3" class="cl"><textarea class="chatTextarea">cc</textarea><button class="makeActive">Make Active</button></div>

Remove dynamic current element

I have form and Add button bottom of te form which is the right..and whenever click it's adding new a form with delete button and if I click it has to delete current form
my js code
$(".iade_sil").on("click",function(){
$(this).parents(".add_after").find(".group").remove();
});
and if you want you can see full demo and js files
codepen demo
You have to register the listener to watch all new elements too. And you want to use closest, not parents.
Even you dont need the closest too, you can select the .group directly, because your delete button is inside that element:
$(document).on("click", ".iade_sil", function() {
$(this).closest(".group").remove();
});
Also you can use closest to that gorup class
$(document).on("click", ".iade_sil", function() {
$(this).closest(".group").remove();
});
You need to use event delegation for attaching events to dynamically added DOM. You should also use .closest() instead of .parents() and traverse to group element:
$(document).on("click",".iade_sil",function(){
$(this).closest(".group").remove();
});

Dynamically created div behavior on button click

I went through many post from SO but not able to relate with my scenario.
I have this code on button click. by which User can create as many div on runtime as he wants to on UI.
$('#adddiv').click(function () {
debugger;
$('#main').append('<div class="ara-dynamic-div">
<div class="box box-solid bg-light-blue-gradient">
</Div></div>');
});
code to get buttonclick event from that div
$(document).on('click', '#remove', function () {
showMakeAndHold(this);
});
function showMakeAndHold(obj) {
alert(obj);
$('.ara-dynamic-div').fadeOut();
}
Now the problem is that I have to create multiple dynamic div. and each div will have button to close itself. When I call this function it will close all created div's instead of the one which button is clicked.
I am not able to find the proper div by which request for close come. I am new to DOM and JQuery. not able to relate the things
First of all, if you're using multiple divs you shouldn't give the close button an ID, but a class instead (let's say, .close)
Next you can use event delegation to find the correct element:
$(document).on('click', '.ara-dynamic-div .close', function( event ) {
$(this).closest('.ara-dynamic-div').fadeOut();
} )
The delegator handles all click events in any .ara-dynamic-div .close button, catching them all and allowing you to use $(this).closest(...) to get to the parent container.
Edit: Corrected a mistake
You can use jQuery's .closest() function.
function showMakeAndHold(obj) {
alert(obj);
$(obj).closest('.ara-dynamic-div').fadeOut();
}
JSFiddle
Replace this:
$(document).on('click', '#remove', function () {
showMakeAndHold(this);
});
by this:
$(document).on('click', '#remove', function () {
$(".ara-dynamic-div").not($(this).parents(".ara-dynamic-div")).fadeOut(function () {
$(this).remove();
});
});
Here is the JSFiddle demo
What the code does is that it remove all other .ara-dynamic-div except the one for which the button was clicked.

jquery trigger event only once on static and dynamic elements

i need to trigger only one click on specific element that can be on page load time or added dynamically in the future. Some code
This code work just fine for elements that are rendered on load time but wont bind the click event to new elements dynamically added
$(".message-actions .accept").one("click", function(e){
console.log("accept");
});
In the other hand if i do it this way, it will bind the event to new elements but don't unbind the event so if i click it again it will print the same console log
$("body").on("click", ".message-actions .accept", function(e){
console.log("decline");
$(this).unbind("click");
});
At last if i do it in this other way it will only fire the event in the first element i click even if there is more than one loaded or added after.
$("body").one("click", ".message-actions .accept", function(e){
console.log("decline");
});
How can i do this?
Thanks
You can add data to the element that remembers whether the handler has run before:
$("body").on("click", ".message-actions .accept", function() {
if (!$(this).data("run-once")) {
console.log("decline");
$(this).data("run-once", true); // Remember that we ran already on this element
}
});
I would do it this way:
var handleClick = function () {
// do your work
alert("decline");
// unbind
$("body").off("click", ".message-actions .accept", handleClick);
};
$("body").on("click", ".message-actions .accept", handleClick);
Check this fiddle
You can solve it like this, if it suits your situation : http://jsfiddle.net/hu4fp5qs/1/
$("body").on("click",".message-actions .accept",function(){
$(this).removeClass("accept").addClass("decline");
alert("Declined");
});
On click remove class accept and add class decline.
This will help you in styling both the cases differently so that you can distinguish between them.
.accept{
background-color:green;
}
.decline{
background-color:red;
}

jQuery Issue: functions won't work on newly created HTML element

I have two functions: one that creates a new <textarea> when a button is clicked, and a second function that performs an action when the <textarea> is clicked (or blurred, changed, etc.) That second function selects elements based on a class name. It seems that the second function only works on those matching elements that existed when the page was loaded, but it will not activate on any newly created <textarea> elements. Can anyone figure out why and how to fix this? You'll find the code below. Thanks. --Jake
$('#add').click(function() {
$(this).before("<textarea class='test'></textarea>")
})
$('.test').blur(function () {
alert('just a test')
})
The textarea you create isn't around at the time jQuery assigns the action to elements tagged with the .test class. You'll need the live() function to make this work as desired.
$('.test').live('blur', function () {
alert('just a test')
});
Now any element tagged with .test will automatically bind the specified function on blur no matter when it's created.
You can bind it directly:
$('#add').click(function() {
$(this).before("<textarea class='test'></textarea>").prev().blur(function () {
alert('just a test');
});
});
Or place use jQuery's .delegate() method to place a handler on the parent of #add.
$('#add').click(function() {
$(this).before("<textarea class='test'></textarea>")
}).parent().delegate('.test','blur',function() {
alert('just a test');
});
This is a more efficient approach than using .live().

Categories