attach event handler to dynamically added element - javascript

I have a javascript code, which adds an element dynamically and event handler to it.this event handler is called (and vanishes) when the element is added.when I see the dynamically added element through inspector(to see if the event handler was added successfully or not) I can't find onchnage="texttol(eletext)" function added it it.
eletext = document.createElement("input");
eletext.type="text";
eletext.placeholder = "Type Here";
eletext.onchange=texttol(eletext);
event.target.appendChild(eletext);

Add your event handling once the element is actually in the DOM.
var eletext = document.createElement("input");
eletext.type = "text";
eletext.placeholder = "Type Here";
eletext.id = "eletext";
document.body.appendChild(eletext);
eletext.addEventListener('change', function(e) {
texttol(eletext.value);
}, false);
function texttol(str) {
alert('texttol function passes: ' + str);
}

With this line, you are calling the method texttol and attaching whatever it returns to the event handler.
eletext.onchange=texttol(eletext);
You need to use a closure
eletext.onchange = function() { texttol(eletext) };
even better, use addEventListener

i have the same issue but the mentioned solutions do not work.
The event handler function theme_onChange is executed on adding each element.
I have a Bootstrap dropdwn menu (#themeDropdownMenu) and want to fill it dynamically with button elements via looping over the "Themes" object properties.
function setThemes () {
var lstThemes = document.querySelector('#themeDropdownMenu');
var newItem;
for ( x in Themes ) {
newItem = document.createElement('button');
newItem.innerHTML = x;
newItem.classList.add('dropdown-item');
newItem.type='button';
lstThemes.appendChild(newItem);
newItem.addEventListener('click', theme_onChange(newItem) );
}
}
function theme_onChange (item) {
/* console.log("Theme: " + item.innerHTML); */
console.log (item);
}
Result:
console logs each added button element.

Related

Binding listener to a dynamically created element

I am using bootstrap's list group to create a row of tabs. When someone clicks on an element in a table, it dynamically creates a new tab and appends it to that list group.
var newtext = "#"+ticket+" - "+parele.find("td:nth-child(3) strong").html();
var closebtn = $("<button>").addClass("close ml-2 mr-n2 newlyaddedclose").html("×");
var newdiv = $("<div>").addClass("d-flex justify-content-between").append(newtext).append(closebtn);
var newa = $("<a>").addClass("list-group-item list-group-item-action").attr("data-toggle","list").attr("href","#ticket"+ticket).attr("id","ticket"+ticket+"-tab").append(newdiv);
$("#ticketpanel").append(newa);
The problem I am having is the newly created close button. I need to bind a function that identifies when that is clicked to handle closing that tab, but it doesn't seem to be working. In my example here, I added the "newlyaddedclose" class to help identify the new element temporarily and I added the following code below to bind a function that is defined at the top of my script tag:
$(".newlyaddedclose").on("click",".close",closebtn).removeClass("newlyaddedclose");
This still doesn't work. When I inspect the close button element, console shows this error: Framework Event Listeners API Errors:
event listener's handler isn't a function or empt
Am I making this harder than it needs to be, or what am I doing wrong? I can simple put at the end of this element creation this:
$(".close").click(function() { ... });
But doing this starts to double up and triple up etc, those events on already created tabs.
EDIT:
Here is my entire block of script to clear up any confusion.
$(function() {
function closebtn() {
alert("Close button clicked...");
}
$(".ticket-line").click(function() {
var parele = $(this);
var ticket = parele.data("tnum");
// Check to see if ticket is already open in tabs
if($("#ticket"+ticket).length == 0) {
// Create tab on ticket panel
var newtext = "#"+ticket+" - "+parele.find("td:nth-child(3) strong").html();
var closebtn = $("<button>").addClass("close ml-2 mr-n2 newlyaddedclose").html("×");
var newdiv = $("<div>").addClass("d-flex justify-content-between").append(newtext).append(closebtn);
var newa = $("<a>").addClass("list-group-item list-group-item-action").attr("data-toggle","list").attr("href","#ticket"+ticket).attr("id","ticket"+ticket+"-tab").append(newdiv);
$("#ticketpanel").append(newa);
$(".newlyaddedclose").on("click",".close",closebtn).removeClass("newlyaddedclose");
// Create DIV with content
var newdata = $("<div>").addClass("tab-pane").attr("id","ticket"+ticket);
$("#ticket-tabs").append(newdata);
$("#ticket"+ticket+"-tab").tab("show");
} else {
// Ticket is already open, switch to it instead
$("#ticket"+ticket+"-tab").tab("show");
}
});
})
The error is clearly stating you are binding a non function to the event listener. So the error is saying that closeBtn is not a function. Your code, you defined closeBtn as the button you are trying to attach the event too. So change closeBtn in the click event listener to the name of the function you are actually trying to call. If it is the same function name, rename something.
Your problem:
var closeBtn = 1;
if (1===1) {
var closeBtn = 2;
console.log(closeBtn);
}
console.log(closeBtn);
It is unclear why you are selecting the element you just added. You can just attach the event when you create the button, no need to look up the element.
var closebtn = $("<button>")...
closeBtn.on("click", function (){
console.log('clicked', closeBtn);
});
Or use event delegation so any element you add will trigger the function.
$("#ticketpanel").on("click", ".close", function () {
const closeBtn = $(this);
console.log('clicked', closeBtn);
});

JQuery removing <li> using onclick event

I have a ul in which I'll add elements using JQuery, I have this
function addElement(e) {
let text = $('#itemToAdd').val();
let newItem = $('<li>' + text + '</li>');
let removeBtn = $('<button onclick = "removeElement">X</button>');
newItem.append(removeBtn);
$('#shoppingList').append(newItem);
$('#itemToAdd').val('');
e.preventDefault();
}
$(document).ready(function() {
$("#addBtn").on('click', addElement);
});
For removing the elements I have this:
function removeElement() {
$(this).parent().remove();
}
The adding function works awesome, but the removing one doesn't.
If you are using onclick then you have to invoke the function with the reference since this won't refer to clicked element(refers to window object most commonly) and based on that remove that element.
Element creation:
let removeBtn = $('<button onclick = "removeElement(this)">X</button>');
Function :
function removeElement(ele) {
$(ele).parent().remove();
}
Or alternately you can use the existing function but bind event handler using jQuery after element creation.
let removeBtn = $('<button>X</button>');
removeElement.click(removeElement);
An another option would be event delegation which helps to handle events on dynamically created elements.

Why two event listeners are triggered instead of one?

I have element which has two event listeners that are triggered depending of his class name. During click event, his className is changing, and this another class has its own different event listener. Two events should be triggered alternately by every click.
During first click listener calls function editClub, but all the next clicks calls two functions. I don't know why that removed-class-event is triggered. Maybe its because after each event function callListeners is executed, and there are multiple listeners on one object? But should be triggered just one. Later I wrote removeListeners function which remove all existing listeners and put her to call just before callListeners function. But then just editClub function is executed by every click. What's wrong with my code?
function callListeners()
{
if ( document.getElementsByClassName('editBtn') )
{
let x = document.getElementsByClassName('editBtn');
for ( let i = 0; i < x.length; i++ )
{
x[i].addEventListener('click', editClub);
}
}
if ( document.getElementsByClassName('saveBtn') )
{
let x = document.getElementsByClassName('saveBtn');
for ( let i = 0; i < x.length; i++ )
{
x[i].addEventListener('click', saveClub);
}
}
}
function editClub(event)
{
event.preventDefault();
this.setAttribute('src','img/\icon_save.png');
this.setAttribute('class','saveBtn');
//removeListeners(); <-- here I placed removeListeners function
callListeners();
}
function saveClub(event)
{
event.preventDefault();
this.setAttribute('src', 'img/\icon_edit.png');
this.setAttribute('class', 'editBtn');
//removeListeners(); <-- here I placed removeListeners function
callListeners();
}
It looks like you are not removing the classes when the click event happens so after the first click the element has both classes.
Just changing an element's class does not change the event listeners that were setup on it previously. They will still be there unless you explicitly remove them, or the elements themselves are destroyed. And you get multiple calls because you keep adding new listeners without removing the old ones.
You could on each click remove the old listener and add the new listener
function editClub(){
this.removeEventListener("click",editClub);
this.addEventListener("click",saveClub);
}
function saveClub(){
this.removeEventListener("click",saveClub);
this.addEventListener("click",editClub);
}
But that is a bit tedious. Instead you can setup a delegated event listener on a static parent like document. Doing so allows for a single event listener which will be called when either button is clicked. Then in that listener you can check the element's class, and execute the appropriate function for it:
function clubAction(event){
//get a reference to the element clicked
var element = event.target;
//call the appropriate function
//or just do the work here
if(element.classList.contains("editClub")){
editClub.call(element,event);
} else if(element.classList.contains("saveClub")) {
saveClub.call(element,event);
}
}
document.addEventListener("click",clubAction);
classList is a property that lets you get,set,remove, and other operations for the classes of the element.
Demo
function clubAction(event) {
var element = event.target;
if (element.classList.contains("editClub")) {
editClub.call(element,event);
} else if (element.classList.contains("saveClub")) {
saveClub.call(element,event);
}
}
document.addEventListener("click", clubAction);
function editClub(event) {
event.preventDefault();
this.classList.remove('editClub');
this.classList.add('saveClub');
this.innerText = "Save";
}
function saveClub(event) {
event.preventDefault();
this.classList.add('editClub');
this.classList.remove('saveClub');
this.innerText = "Edit";
}
.saveClub {
background:#0F0;
}
.editClub {
background:#FF0;
}
<button class="saveClub">Save</button>
<button class="editClub">Edit</button>

How can we pass an element to event handler in javascript

I have created an <input> HTML element using Javascript. Now I want to add an onblur event handler to this element dynamically. However I do not understand how I can pass the created element as an argument to the function. Here's my code:
element = document.createElement("input");
element.onblur = hello_function;
In the above code you can see that the element is created. Now I want to pass that element to hello_function. How can I do that?
function hello_function(element) {
alert(element);
}
To achieve this you can wrap the hello_function call in an anonymous function wrapper and provide the this argument:
element = document.createElement("input");
element.addEventListener('blur', function() {
hello_function(this);
});
document.body.appendChild(element);
function hello_function(element) {
console.log(element);
}
Also note the preferred use of addEventListener over onblur.
try like this. passing the another variable into a function,
var something="hello";
var element = document.createElement("input");
element.addEventListener('blur' , function ()
{
hello_function(something);
})
document.body.appendChild(element)
function hello_function (element){
alert(element);
}
i suggest to use addEventListener, also i think you need to append the created element to the document, something like this:
var elem = document.createElement("input");
if (elem) {
elem.addEventListener('blur', hello_function, false);
}
document.body.append(elem);
function hello_function(element) {
alert(element);
}

How can I attach event to a tag which is in string form?

I'm creating html on runtime like this:
var myVar = "<div id='abc'>some clickable text</div>"
Now, I want to attach some event, say onclick, to this div. How can I do that on next line? I'll add this to DOM later.
PS: I've to accomplish this without using JQuery.
Instead of building your div as a string, you'll want to use document.createElement('div'). This way you will have a real dom object, and can get and set it's propeties, including onClick
Will this help? Since you dynamically generate it, you know the control id of the DIV.
document.getElementbyId('abc').onClick = foo;
function foo()
{
alert("All your impl to go here");
}
Try building the div as a DOM element first.
var myVar = document.createElement("div"),
parentDiv = document.getElementById("parent_div");
parentDiv.appendChild(myVar);
myVar.innerHTML = "some clickable text";
if(myVar.addEventListener){
myVar.addEventListener("click", clickFn, false);
}
else if(myVar.attachEvent){
myVar.attachEvent("onclick", clickFn);
}
else{
myVar.onclick = clickFn;
}
The addEventListener method is standard, but not every browser plays nice with the standard.
EDIT: As mentioned, an element must be added to the DOM first.
Or you can use this technique: attach event to the document.body. Then if the event target is not the needed div than just do nothing. It is the same techinque jquery uses for its live function:
// crossbrowser event attachment function
function listen(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt, func, false);
}
else if (elem.attachEvent) {
var r = elem.attachEvent("on" + evnt, func);
return r;
}
else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
}
// this is an analog of the jquery.live
var assignLiveEvent = function(id, evnt, callback) {
var handler = function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.id == id) {
//your code here
callback(e);
}
};
listen(evnt, document.body, handler);
};
var myVar = "<div id='abc'>some clickable text</div>";
assignLiveEvent("abc", "click", function(e) {
//your code here
});
// now you can add your div to DOM even after event handler assignation
Here is demo.
Brian Glaz is totally right but, if for some reason, you really need to do it this way, you have two options:
you can only add events to something that is already in the DOM, using pure javascript, so you would have to include it in the html like:
document.body.innerHTML += myVar;
and then, attach the event with
document.getElementById('abc').addEventListener('click', function(e){
//your code
}, 1);
With jQuery, you could use .live() to attach events to elements that are not yet present in the DOM:
$('#abc').live('click', function(e){
//your code here
});
so you could add the div later...

Categories

Resources