My HTML page has the following controller setup:
...
<div data-controller="parent">
<div data-target="parent.myDiv">
<div data-controller="child">
<span data-target="child.mySpan"></span>
</div>
</div>
</div>
...
The child controller is linked to the child_controller.js
class shown below:
export default class {
static targets = ["mySpan"];
connect() {
document.addEventListener("myEvent", (event) => this.handleMyEvent(event));
}
handleMyEvent(event) {
console.log(event);
this.mySpanTarget; // Modifying the span works fine.
}
}
An issue arises when I replace the contents of the target myDiv
from my parent_controller.js
:
...
let childControllerHTML = "<div data-controller="child">...</div>"
myDivTarget.innerHTML= childControllerHTML;
...
After replacing the child HTML, the event listener triggers twice whenever the myEvent
occurs. Subsequent replacements cause the event to be logged multiple times.
I understand that using document.removeEventListener
can prevent the old controller from listening to events:
export default class {
static targets = ["mySpan"];
connect() {
this.myEventListener = document.addEventListener("myEvent", (event) => this.handleMyEvent(event));
}
disconnect() {
document.removeEventListener("myEvent", this.myEventListener);
}
handleMyEvent(event) {
console.log(event);
this.mySpanTarget; // Fails to find span.
}
}
However, using this approach causes the handleMyEvent
method to lose its context as it cannot locate mySpanTarget
anymore under this
.
Is there a way to remove the listener from the child controller which is no longer in the DOM while maintaining the necessary context?