Events
by Julian Rubisch
Register Global Events in Your Markup
Bad
connect() { document.addEventListener(...); }
Good
<div data-controller="gallery" data-action="resize@window->gallery#layout">...</div>
layout(e) { ... }
Rationale
Stimulus will handle the adding and removing of event listeners.
Contraindications
The controller code makes assumption about the markup, which may not be feasible if you’re creating a Stimulus controller library. In this case, be sure to unregister your event listeners in disconnect
.
Why does this happen?
A stimulus controller can connect
/ disconnect
an arbitrary number of times. If eventListeners added in connect
are not cleaned up on disconnect
, you will have more than one eventListener for the given element and thus run your event listener callback multiple times instead of just once.
How to cleanup event listeners in connect / disconnect
Bad
connect() { document.addEventListener("click", this.findFoo.bind(this)) } disconnect() { document.removeEventListener("click", this.findFoo.bind(this)) } findFoo() { console.log(this.element.querySelector("#foo")) }
Good
connect() { this.boundFindFoo = this.findFoo.bind(this) document.addEventListener("click", this.boundFindFoo) } disconnect() { document.removeEventListener("click", this.boundFindFoo) } findFoo() { console.log(this.element.querySelector("#foo")) }
Why is the first one bad?
When you call .bind()
on a function, it creates a new function. Therefore, calling bind twice means the
add and remove eventListeners are calling different references of the function and the event wont be removed.
Make sure that when adding and removing event listeners you use the same bound function reference.