Remove a JavaScript class method from eventlistener inside another method of the same class

64 Views Asked by At

Description & Goal

I have a list with items and clicking on an item shows a detail view, shows a close button and add the eventlistener for closing this item to the button. By clicking on this button the detail view should be closed and the eventlistener should be removed.

I can't use an anonymous function because removing won't work with it (See here and here).

Problem

Removing doesn't work.

Code

export default class ToggleDetails {
  constructor(jobAdId) {
    this.jobAdId = jobAdId
    this.opened = false
  }

  toggle() {
    const jobAdContainer = document.getElementById(this.jobAdId)
    // doing some other css manipulation for the detail view
    this.handleCloseButton()
  }

  handleCloseButton() {
    const closeButton = document.getElementById('uh-job-detail-close-button')

    const $this = () => {
      this.toggle()
    }

    if (this.opened === true) {
      closeButton.classList.remove('uh-job-detail-close-button-show')
      closeButton.removeEventListener('click', $this)
      this.opened = false
    } else {
      closeButton.classList.add('uh-job-detail-close-button-show')
      closeButton.addEventListener('click', $this)
      this.opened = true
    }
  }
}

HTML structure enter image description here

"Solution"/Workaround

I solved it, by cloning and replacing the button with itself. The clone doesn't have the eventlisteners (Thanks to this post)

handleCloseButton () {
    const closeButton = document.getElementById(
      'uh-job-detail-close-button')
      
    closeButton.classList.toggle('uh-job-detail-close-button-show')

    if (this.opened === true) {
      const elClone = closeButton.cloneNode(true)
      closeButton.parentNode.replaceChild(elClone, closeButton)
      this.opened = !this.opened
    } else {
      closeButton.addEventListener('click',
        () => { this.toggle() })
      this.opened = !this.opened
    }
  }
1

There are 1 best solutions below

6
On

Try using a named function and passing the value of this into toggle:

export default class ToggleDetails {
  constructor(jobAdId) {
    this.jobAdId = jobAdId
    this.opened = false
  }

  toggle(t) {
    // doing some other css manipulation for the detail view
    t.handleCloseButton()
  }

  handleCloseButton() {
    const closeButton = document.getElementById('uh-job-detail-close-button')

    let listenerToggle = () => {
       this.toggle(this);
    };

    if (this.opened === true) {
      closeButton.classList.remove('uh-job-detail-close-button-show')
      closeButton.removeEventListener('click', listenerToggle)
      this.opened = false
    } else {
      closeButton.classList.add('uh-job-detail-close-button-show')
      closeButton.addEventListener('click', listenerToggle)
      this.opened = true
    }
  }
}