Search code examples
reactjsecmascript-6event-handlingdom-eventsmouseevent

Es6 class with event handlers and issues with context/scope


I have a container with two panes. I am making one of them re-sizable and absolute, and the other adjusts in real time based on the size of the first.

Unfortunately I am having problems with the es6 "resize-controller" that I just wrote. Because I made the wrong decision to use arrow functions, I am unable to remove the event listeners. Other than that and a bug with my math, it is functioning as expected. However when I tried to fix my mistakes with several possible solutions, I either get no functionality or errors about context and functions not being functions.

Hoping someone here could take a look at my exact setup and show me how it should be. Replacing the Arrow functions with normal functions, with or without event params, does not work. Would I be better off ditching Es6 classes for this one? Perhaps I have unlocked a few layers of complexity.

class ResizeController {

constructor(){
    this.chatContainer = document.getElementById("chatContainer");
    this.messageWindowContainer = document.getElementById("messageWindowContainer");
    this.messageWindowContentContainer = document.getElementById("messageWindowContentContainer");
    this.messageWindowContent = document.getElementById("messageWindowContent");
    this.startX = "";
    this.startWidth = this.getMessageWindowWidth();
}

init(){
    this.messageWindowContainer.addEventListener('mousedown', (e)=>{e.stopPropagation()});
    this.messageWindowContentContainer.addEventListener('mousedown', (e)=>{this.onMouseDown(e)});
    this.messageWindowContent.addEventListener('mousedown', (e)=>{e.stopPropagation()})
}

onMouseDown(e) {
    this.onDown(e);
    e.preventDefault();
}

onDown(e){
    this.startX = e.clientX;
    this.messageWindowContentContainer.addEventListener('mousemove', (e)=>{this.onMouseMove(e)});
    this.messageWindowContentContainer.addEventListener('mouseup', (e)=>{this.onMouseUp(e)});
}

onMouseMove(e){
    this.mouseMove(e);
    e.preventDefault();
}

onMouseUp(e){
    this.mouseUp(e);
    e.preventDefault();
}

mouseMove(e) {
        this.messageWindowContainer.setAttribute("style","width:"+( this.startWidth - e.clientX + this.startX)+"px");
}

mouseUp(e){
    console.log("stopdrag")
    this.messageWindowContentContainer.removeEventListener('mousemove', (e)=>{this.onMouseMove(e)});
    this.messageWindowContentContainer.removeEventListener('mouseup', (e)=>{this.onMouseUp(e)});
}


getMessageWindowWidth(){
    let chatContainerWidth = document.getElementById("chatContainer").offsetWidth;
    let messageWindowContainerWidth = document.getElementById("messageWindowContainer").offsetWidth;
    return (chatContainerWidth - messageWindowContainerWidth);
}


}


export default ResizeController

Solution

  • Answer found here: https://gist.github.com/Restuta/e400a555ba24daa396cc

    I simply defined the following code once in my constructor and then used them as my event handlers.

    this.bound_onMouseDown = this.onMouseDown.bind(this); this.bound_onMouseMove = this.onMouseMove.bind(this); this.bound_onMouseUp = this.onMouseUp.bind(this);

    Declaring them outside the constructor is not a solution.