Stimulus Discourse

Remove listen to animation end


#1

I’m trying to hide a div after it has been faded out but I’m having a hard time removing the event listened once fired up.

   import { Controller } from "stimulus"

export default class extends Controller {
  static targets = ["field", "displayFieldButton", "hideFieldButton"]

  connect() {
    this.fieldTarget.classList.add("is-hidden")
    this.hideFieldButtonTarget.classList.add("is-hidden")
  }

  displayField() {
    this.fieldTarget.classList.toggle("is-hidden")
    this.fieldTarget.classList.add("fadeIn")


    this.displayFieldButtonTarget.classList.toggle("is-hidden")
    this.hideFieldButtonTarget.classList.toggle("is-hidden")
  }

  hideField() {
    this.fieldTarget.classList.remove("fadeIn")
    this.fieldTarget.classList.add("fadeOut")
    console.log('before addevent')
    this.fieldTarget.addEventListener(this.animationEnd(), event => {
      this.removeField()
    }, false)
    console.log('after addevent')

    this.hideFieldButtonTarget.classList.toggle("is-hidden")
    this.displayFieldButtonTarget.classList.toggle("is-hidden")
  }

  removeField() {

    this.fieldTarget.removeEventListener(this.animationEnd(), event => {
        this.removeField()
      }, false)

      this.fieldTarget.classList.add("is-hidden")
      console.log('after removing')

  }

  animationEnd() {
    console.log('nimating')
    var animations = {
      animation:        "animationend",
      OAnimation:       "oAnimationEnd",
      MozAnimation:     "mozAnimationEnd",
      WebkitAnimation:  "webkitAnimationEnd",
    };

    let elem = document.createElement('div')
    for (var t in animations) {
      if (elem.style[t] !== undefined) {
        console.log(animations[t])
        return animations[t]
      }
    }
  }


}

Everything works fine the first time I run hideField but if I call it a second time, removeField is called right after displayField.

Why removeEventListener isn’t working?


#2

Can we see the entire controller please?

Have a feeling your reference to ‘this’ isn’t referencing the ‘this’ you want properly.


#3

Sure, see updated code above.
Thank you.


#4

You need to remove the exact same event handler function that was added. It’s not working because you’re passing anonymous inline functions to both addEventListener and removeEventListener.

Here’s one way you can fix that:

initialize() {
  this.removeField = this.removeField.bind(this)
}

hideField() {
  // …
  this.fieldTarget.addEventListener(this.animationEnd(), this.removeField)
  // …
}

removeField() {
  this.fieldTarget.removeEventListener(this.animationEnd(), this.removeField)
  // …
}

Or, you could create a handler that removes itself and keep a reference to it:

hideField() {
  // …
  let handler
  this.fieldTarget.addEventListener(this.animationEnd(), handler = () => {
    this.fieldTarget.removeEventListener(this.animationEnd(), handler)
    this.removeField()
  })
  // …
}

#5

Thanks for finding the time to help me out.