Dynamically mounting an action to Stimulus #825
Replies: 9 comments
-
|
Would declaring an event listener within your controller suit your needs? // dropdown controller
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
addEventListener("click", this.hide)
}
disconnect() {
removeEventListener("click", this.hide)
}
hide = (event) => {
// ...
}
}If you'd need to conditionally listen based on some other // dropdown controller
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
disconnect() {
removeEventListener("click", this.hide)
}
expand() {
// ... show the dropdown
addEventListener("click", this.hide)
}
hide = (event) => {
// ... hide the dropdown
removeEventListener("click", this.hide)
}
} |
Beta Was this translation helpful? Give feedback.
-
|
@seanpdoyle thanks for coming back to me! Indeed, it is possible to do so, this is my current implementation: import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["button", "dropdown"]
toggle (event, shouldHide) {
let hidden = !!shouldHide ? shouldHide : this.dropdownTarget.classList.contains("hidden")
this.dropdownTarget.classList.toggle("hidden", !hidden)
this.dropdownTarget.setAttribute("aria-expanded", !hidden.toString())
hidden ? addEventListener("click", this.hide, true) : removeEventListener("click", this.hide, true)
}
hide = event => {
if (!this.buttonTarget.contains(event.target)) this.toggle(true)
}
}However, I think there are several drawbacks:
|
Beta Was this translation helpful? Give feedback.
-
|
How about this implementation @elvinaspredkelis ? https://stimulus-use.github.io/stimulus-use/#/use-click-outside
|
Beta Was this translation helpful? Give feedback.
-
|
Sorry to waist everyones bandwidth here - but I can't help thinking if the issue is related to my "observation" ? (quick resumé: if an element is 'hidden' it's action will not "work" if the element at some later point in time gets 'unhiddened' - or, that's my observation, at least, and as I duly posit: I'm sure it's on me) am I way off here? |
Beta Was this translation helpful? Give feedback.
-
|
Would the 3.1.1 feature See docs - https://stimulus.hotwired.dev/reference/actions#options |
Beta Was this translation helpful? Give feedback.
-
|
Another way to dynamically add an action is to actually (re)-write the this.element.dataset.action = `click->${this.identifier}#myDynamicAction`or if you want the respect the previous value: this.element.dataset.action = `${this.element.dataset.action} click->${this.identifier}#myDynamicAction`We could also abstract it away in a function call itself, here's a rough sketch from a few months ago: https://gist.github.com/marcoroth/64c308d9e7be047a2061469ebe58daea |
Beta Was this translation helpful? Give feedback.
-
|
@marcoroth do you know if a specific version of stimulus is required to dynamically add an action by re-writing the |
Beta Was this translation helpful? Give feedback.
-
|
Hey @MrHubble, no this shouldn't be version dependent as it's just setting an attribute via the native DOM API. Can you share what you've got? |
Beta Was this translation helpful? Give feedback.
-
|
@marcoroth of course after coming back to this I can no longer replicate this issue 🤦♂️ |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hey!
First of all, I am a big fan of Stimulus 🎉
Recently, I found myself missing a way to dynamically adding actions. Is there a way to do so? Or, perhaps, there only be a way to do it eventually?
Use case
Handling a dropdown menu via JS, for example. Currently, I am collapsing such menus via something like
click@window->dropdown#hidewhich is not ideal: it adds a lot of unnecessary events, fills up the debug mode and it only gets worse if there are more such dropdowns.Obviously, it is possible add
window.addEventListener(...), however, it becomes "detached" from the controller. So it would be nice to keep things consistent.Expected functionality
Perhaps having an exposed
Actionclass and/or mounting method could be an option.Referring to the above mentioned use case, it would be possible to mount a new action when the dropdown is opened:
new Action(element, index, descriptor)and then destroy this action upon disconnect.P.s.
Not sure if this is a question or a feature request. I have tried searching for an answer, however, with no luck. Also, I am not that sure if this is a bad practice and/or is inconsistent with the Stimulus codebase or the way it is mounted.
Beta Was this translation helpful? Give feedback.
All reactions