I am trying to remove some listeners attached to certain array of elements.
As I am adding the event listeners I cannot get a reference to the parameters I needs. I have been doing some research and found out that can be solved using closures, but I can't figure out very well how to do it
here is my function reference
const editTask = function (element, taskIndex) {
const handler = function(event) {
// my code ...
}
}
and this is how I am adding the listeners
function addEditListeners() {
const editButtons = [].slice.call(document.getElementsByClassName("edit-btn"));
console.log('editbuttons', editButtons);
//editButtons.forEach(function (element) {
// element.removeEventListeners("click", editTask);
//});
editButtons.forEach(function (element, index) {
element.addEventListener("click", handler);
});
}
I have tried sending the parameters in parenthesis but the editTask is undefined, what am I doing wrong?
Notice that you are passing handler which only exists in the editTask function and nowhere else, your listener adding function should be like this
editButtons.forEach(function (element, index) {
element.addEventListener("click", (e) => editTask(element, index, e));
});
Also I see you want an event in there as well so you should pass it in edit task
const editTask = function (element, taskIndex, event) {
const handler = function(event) {
// my code ...
}
handler(event);
}
Related
I am adding an event listener which needs the event properties as well as other parameters
document.body.addEventListener("click", (e) =>
listenForMembersOpen(e, buttonReplacement, openEditModal)
);
I need to remove this event listener when my component unmounts but running:
document.body.removeEventListener("click", (e) =>
listenForMembersOpen(e, buttonReplacement, openEditModal)
);
doesn't seem to get the job done. I'm thinking it is because the function declaration within the event listener. Any advice on how I can remove the event lister shown?
export function addListenersForButtonReplacement(buttonReplacement, openEditModal) {
document.body.addEventListener("click", (e) =>
listenForMembersOpen(e, buttonReplacement, openEditModal)
);
document.body.addEventListener("keydown", (e) =>
listenForMembersOpen(e, buttonReplacement, openEditModal)
);
}
If you've ever tried comparing equality for an object, you know that:
const a = { v: 1 };
const b = { v: 1 };
a !== b
a != b
a === a
b === b
And that applies to functions as well.
When you call addEventListener, it doesn't toString() the input function, and when the event listener is removed, check for equality. Instead, it stores the "reference", the function you passed to as an argument, and compares that.
The way you'd use it, then, is by passing the same variable to removeEventListener as to addEventListener, like this:
// create a separate function to handle the event
const eventHandler = (e) => listenForMembersOpen(e, buttonReplacement, openEditModal);
document.body.addEventListener("click", eventHandler);
// later...
document.body.removeEventListener("click", eventHandler);
Simply passing the same function body content (meaning when you toString() it the value will be the same) will not be recognized as the same event listener.
In your context, you'll need to export that function to be used elsewhere, perhaps by returning that value from the exported function, like this:
export function addListenersForButtonReplacement(buttonReplacement, openEditModal) {
const eventHandler = (e) => listenForMembersOpen(e, buttonReplacement, openEditModal);
document.body.addEventListener("click", eventHandler);
document.body.addEventListener("keydown", eventHandler);
// "export" it by returning:
return eventHandler;
}
Later when you're using it elsewhere...
import { addListenersForButtonReplacement } from "./somewhere";
// later...
const evFn = addListenersForButtonReplacement(/* ... */);
// later... (we have the same "reference" to the function)
document.body.removeEventListener("click", evFn);
document.body.removeEventListener("keydown", evFn);
yeah. you need to have a single function otherwise javascript won't be able to find the function reference
function listener (e) {
listenForMembersOpen(e, buttonReplacement, openEditModal)
}
document.body.addEventListener("click", listener);
document.body.removeEventListener("click", listener);
I have a dynamic button that supposed to remove his parent element from the DOM.
Because its dynamic, i warpped it with DOMContentLoaded and added for each button the EventListener with 'click'.
Somehow, i dont get into the callback function (deleteTodo) when click.
I'll happy to know what im doing wrong.
Thanks :)
document.addEventListener('DOMContentLoaded', (event) => {
let deleteBtn = document.getElementsByClassName('delete-btn');
for( let btn of deleteBtn)
btn.addEventListener('click', deleteTodo);
});
// Delete element
const deleteTodo = () => {
console.log("inside function"); // I DONT GET INTO THIS LINE WHEN CLICK
}
You can't call a function assigned to a variable that hasn't been initialised. Use a function declaration (they're automatically hoisted) rather than a function expression so you can ensure that when your code tries to add the function to the listener it's actually available. And, as you can see from the example, it doesn't matter where you add the declaration.
function addThings() {
const html = [];
for (let i = 0; i < 5; i++) {
html.push(`<div>${i} <button class="delete-btn">Delete</button></div>`)
}
return html.join('');
}
document.body.innerHTML = addThings();
const buttons = document.querySelectorAll('.delete-btn');
buttons.forEach(button => {
button.addEventListener('click', deleteTodo, false);
});
function deleteTodo() {
this.parentNode.remove();
}
I have:
e.addEventListener("click",()=>{alert(this.innerText);});
and I need to be able to remove it.
If I don't use an anonymous function so that I can use removeEventListener, how to I pass this to the named function?
function f() {
//how do I access the "this"?
}
e.addEventListener("click", f);
The only problem you have is that you don't have any handle on your function since you're declaring it inline. All you need to do is move that same declaration and assign it to a variable:
const cb = () => alert(this.innerText);
e.addEventListener('click', cb);
e.removeEventListener('click', cb);
I usually just create a friendlier function to work with.
const listen = (el, ...args) => {
el.addEventListener(...args);
return{
remove: () => el.removeEventListener(...args)
};
};
So you can just do things like...
const listener = listen(document, 'click', () => {
console.log('click');
listener.remove();
});
I have no idea of how to do this, I want to pass an argument to the callback function "ctrlDeleteItem":
document.querySelector('.container').addEventListener('click', ctrlDeleteItem);
But if I do that, I lose access to the event property, example:
document.querySelector('.container').addEventListener('click', ctrlDeleteItem(item));
function ctrlDeleteItem(item, event) {
return function() {
console.log(item);
console.log(event);
}
}
How can I still pass the event as a parameter? I can't find how to do it, thanks.
The accepted answer is incorrect because it will cause the ctrlDeleteItem function to be executed immediately. That can be shown by adding a console.log("test") statement to the ctrlDeleteItem() function - you'll get the message immediately.
The correct solution is to set up a "wrapper" callback function that will receive the event as usual and then have that wrapper call the actual callback function with whatever arguments are needed. The wrapper can pass the event to the actual callback if desired.
const item = 'foo';
document.querySelector('.container').addEventListener('click', function(evt){
ctrlDeleteItem(evt, item);
});
function ctrlDeleteItem(evt, item) {
console.log(evt.type, item);
console.log(event.target.className);
}
<div class="container">container</div>
Put event as an argument to the returned function in ctrlDeleteItem, so that it will be used properly as the event in the listener:
function ctrlDeleteItem(item) {
return function(event) {
console.log(item);
console.log(event);
}
}
const item = 'foo';
document.querySelector('.container').addEventListener('click', ctrlDeleteItem(item));
function ctrlDeleteItem(item) {
return function(event) {
console.log(item);
console.log(event.target.className);
}
}
<div class="container">container</div>
there! i have a problem when creating one function just like JQUERY does.
here is the action : https://jsfiddle.net/77yzLt6v/
one time execution event
HTML :
<div id="justOnce">click me!</div>
function one(dom, event, callback) {
dom.addEventListener(event, function(e) { // add event
this.removeEventListener(event, callback); // remove it
});
}
one(document.getElementById("justOnce"), "click", function() {
alert("this alert only show once time");
});
what's wrong with my code?
thanks in advance...
Your code binds an event handler that removes callback as an event handler.
The only problem is … you never bound callback as an event handler in the first place.
You want something more like this:
function one(dom, event, callback) {
function handler(e) {
callback.call(this, e);
this.removeEventListener(event, handler);
}
dom.addEventListener(event, handler);
}
i.e.
You need to call the callback
You need to remove the event handler you actually bound
New standard supports this, but don't work in any browser yet (caniuse.com)
window.addEventListener('resize', console.log, {once: true})
polyfill:
;(function(){
let p = document.createElement('p')
let count = 0
let event = new CustomEvent('x')
p.addEventListener('x', () => {i++})
p.dispatchEvent(event)
p.dispatchEvent(event)
if (i != 2) return
for (let obj of [Window, Element]) {
let orig = obj.prototype.addEventListener
function addEventListener(type, callback, opts) {
let args = Array.from(arguments)
if(opts && opts.once) {
function handler(e) {
callback.call(this, e)
this.removeEventListener(type, handler)
}
args[1] = handler
}
orig.apply(this, args)
}
obj.prototype.addEventListener = addEventListener
}
}())