JavaScript Event Listeners inside methods [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I was hoping to be able to call object methods from an event listener, however, I am unable to access object properties on the called function:
import {action} from '../desktopIntegration/actions.js'
class Object {
constructor() {
this.property = 2
}
addListener() {
action.on("keyup", this.printEvent)
}
printEvent() {
console.log(this.property)
}
}
This code gives the error:
unable to access property of undefined
when addListener is called.
Is there a way to make this work? I want to keep the callback as a method function so that I can delete the listener on each instance of Object.
Thanks!

Instance methods are not bound to the class instance by default. If a method is being used as an event listener, it is by default bound to the element emitting the event.
To fix that, you need to overwrite your method in the constructor, by a version bound to the class instance:
class Foo {
constructor() {
this.property = 2
this.printEvent = this.printEvent.bind(this)
this.addListener()
}
addListener() {
document.getElementById('action').addEventListener("keyup", this.printEvent)
}
printEvent(event) { // added the event argument, gets automatically passed to the listener
console.log(this.property)
console.log(event.target.value) // to access the event emitting element, use event.target
}
}
const bar = new Foo();
<input id="action" />
Also note that you should NEVER call your class Object.

Related

Why is "this" keyword undefined when invoked by inline event handler in React, but it refers to the caller when invoked by post-render event listener? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 1 year ago.
const Event = () => {
// useEffect(()=>{
// document.getElementById('btn').addEventListener('click', function() {
// console.log(myObj.showThis())
// })
// })
const myObj = {
name: 'romeo',
showThis: function() {
console.log(this)
}
}
return (
<div>
<button id='btn' onClick={myObj.showThis} >Fire Event</button>
</div>
)
}
In here, I am adding inline event handler which invokes the myObj.showThis method, and when it does, the console logs out undefined, but if I instead use the useEffect() hook to add event listener to the button, which invokes the same myObj.showThis function, now the console logs out the caller, which is the button, so this refers to the caller, but why is this undefined when I invoke the same method via inline event handler?
You need to understand how 'this' works. it references different value depending on the context it is called. this may return different value for myObj.showThis() even inside the useEffect. This is not a factor of the useEffect rather For example
useEffect(()=>{
console.log(myObj.showThis()) // undefined because this is undefined in that context
document.getElementById('btn').addEventListener('click', function() {
// here `this` references the actual object because it defined here as myObj
console.log(myObj.showThis())
})
})
and this is undefined because reactES6 does not auto bind this for function or methods

I'm confused with Event Handler Callback function as a class method? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I know this may seems silly but I'm a beginner and I just need to make sure that I understand it well:
In JavaScript when I define an event listener, the callback function is called without () to prevent immediate execution, like the below example:
document.querySelector('#button').addEventListener('click',eventHandler)
function eventHandler() {
alert('clicked')}
my confusion is if implemented the above in a class and defined the eventHandler callback function as a method, I have to use () when I call it, like the below example:
class home {
constructor(){
this.button = document.querySelector('#button')
this.clickEvent()
}
//events
clickEvent(){
//here i have to use eventHandler() not eventHandler
this.button.addEventListener('click',()=>this.eventHandler())
}
//method
eventHandler(){
alert('clicked')
}
}
new home()
In code snippet with class, you are passing a function to addEventListener function which then calls the eventHandler function.
() => this.eventHandler() is an arrow function which executes this.eventHandler() inside its body
if you remove the arrow function then you will have to pass the name of the function instead of calling it
this.button.addEventListener('click', this.eventHandler)
Edit:
keep in mind that if the eventHandler method uses this, then you may run into problems because of how value of this is set in different cases.
Currently, eventHandler function isn't using this but you should read how to access correct this inside callbacks.

Method not recognized even though it is from the same class in Javascript [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
Recently, I've come across this problem where I had two methods in a class. One was referring to another but the other wasn't being recognized even though I could execute them individually.
class ButtonProcessor {
buttonClick() {
this.otherMethod();
}
otherMethod() {
console.log("This does not work!");
}
}
var buttonProcessor = ButtonProcessor;
document.getElementById("button").onclick = buttonProcessor.buttonClick;
The first method was called from a button click which was associated with a callback to that method.
One solution I found for this is to make the method that is called by the button a seperate function from the class and make it reference a class object that was already being used else-where. This is because apparently, when a method is referenced in a callback, using this to refer to another method doesn't work, because the callback only considers that one method.
class ButtonProcessor {
otherMethod() {
console.log("This does work!");
}
}
var buttonProcessor = ButtonProcessor;
function buttonClick() {
buttonProcessor.otherMethod();
}
document.getElementById("button").onclick = buttonProcessor.buttonClick;
Could there be another way to fix this?

How to call a class method from inside same class method? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I've created a class and I'm trying to call a method from inside that class from another method inside that same class. I've seen online that some people say use 'this' keyword, but as you can see from the example, that doesn't work. Can someone please explain in simple terms how to call a class method from inside another method in that same class? Thanks!
class Form {
constructor() {
}
fn1 () {
console.log('fn1 calling fn2 now:')
this.fn2();
}
fn2 () {
console.log('fn1 called me')
}
}
let myForm = new Form();
myForm.fn1();
Example can be found here
The error I keep getting is this: Uncaught TypeError: this.fn2 is not a function
There's nothing wrong with the code you show embedded into your question - that should work just fine. The issue arises when you pass a method to .addEventListener() as a callback (which shows in the code you have a link to).
Change this:
document.getElementById('call-func').addEventListener('click', this.fn1);
to this:
document.getElementById('call-func').addEventListener('click', this.fn1.bind(this));
The problem is that passing this.fn1 loses the value of this so when the listener calls the callback later, the object that it belongs to is lost and then this inside of fn1() is wrong. In addition, .addEventListener() explicitly sets the this value to the DOM element that triggered the event (which is not your object).
The same thing would happen if you did this:
let f = this.fn1;
f();
Using .bind(this) rebinds the value of this when the listener calls it.
FYI, you could also do it this way with a fat-arrow function:
document.getElementById('call-func').addEventListener('click', () => this.fn1());
Or, an older way of doing it:
var self = this;
document.getElementById('call-func').addEventListener('click', function() {
self.fn1();
});
My preference is to use .bind(this).
More explanation on event listeners and this here: "This" within es6 class method
More explanation on the general concept of how this gets set when a function is called here: When you pass 'this' as an argument

SignalR class method callback and 'this' [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
I had a similar question but not the same. This one focuses on the new ES6 class keyword and how to handle this. SignalR is calling a class method. When inside that class method 'this' refers to the SignalR hub not the class instance itself. How can I get the class instance inside this class member that SignalR called using the new ES6 classes?
class gameLoad {
constructor(){
}
init(){
// create the network object and hook it's functions update for loading
this.network = $.connection.testHub;
this.network.client.hello = this.sayHello;
}
// this is called from signalR and 'this' now refers to the signalR hub inside this function. how can I get the class instance?
sayHello(){
console.log(this); // 'this' refers to signalR object not gameLoad object
}
create(){
var self = this;
$.connection.hub.start().done(function () {
console.log("Started!")
console.log("Calling server function.");
// make our first network call which will turn around and call client.hello which is bound to this classes sayHello() member function
self.network.server.hello();
});
}
}
When using classes, it's best to use arrow functions so that you have 'this' properly set.
In your example, you assign sayHello to client's hello method. You will need to bind gameLoad to it at that time:
this.network.client.hello = this.sayHello.bind(gameLoad);
Alternatively, you can convert sayHello into an arrow function:
sayHello = () => {

Categories

Resources