Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom Action Options #567

Merged
merged 2 commits into from
Jul 28, 2022
Merged

Conversation

seanpdoyle
Copy link
Contributor

@seanpdoyle seanpdoyle commented Jul 28, 2022

As a follow-up to hotwired/stimulus#535 and
hotwired/stimulus#546, add support for declaring custom action
modifiers in the same style as :prevent, :stop, and :self.

Take, for example, the toggle event. It's dispatched whenever a
<details> element toggles either open or closed. If an application
were able to declare a custom open modifier, it could choose to route
toggle events denoted with :open only when the <details open>.
Inversely, they could choose to route toggle events denoted with
:!open only when the <details> does not have [open].

Similarly, the same kind of customization could apply to custom events.
For example, the turbo:submit-end fires after a <form>
element submits, but does not distinguish between success or failure. A
:success modifier could skip events with an unsuccessful HTTP response
code.

Preview of changes to the Actions documentation page:

You can register your own action options with the Application.registerActionOption method.

For example, consider that a <details> element will dispatch a toggle
event whenever it's toggled. A custom :open action option would help
to route events whenever the element is toggled open:

import { Application } from "@hotwired/stimulus"

const application = Application.start()

application.registerActionOption("open", ({ event }) => {
  if (event.type == "toggle") {
    return event.target.open == true
  } else {
    return true
  }
})

Similarly, a custom :!open action option could route events whenever the
element is toggled closed. Declaring the action descriptor option with a !
prefix will yield a value argument set to false in the callback:

import { Application } from "@hotwired/stimulus"

const application = Application.start()

application.registerActionOption("open", ({ event, value }) => {
  if (event.type == "toggle") {
    return event.target.open == value
  } else {
    return true
  }
})

In order to prevent the event from being routed to the controller action, the
registerActionOption callback function must return false. Otherwise, to
route the event to the controller action, return true.

The callback accepts a single object argument with the following keys:

Name Description
name String: The option's name ("open" in the example above)
value Boolean: The value of the option (:open would yield true, :!open would yield false)
event Event: The event instance
element Element: The element where the action descriptor is declared

@seanpdoyle seanpdoyle force-pushed the custom-action-options branch from a301681 to 98e0815 Compare July 28, 2022 18:01
@dhh
Copy link
Member

dhh commented Jul 28, 2022

Love it! And I actually love the two examples you're giving enough that I think they're worth adding as defaults too.

@seanpdoyle seanpdoyle force-pushed the custom-action-options branch 3 times, most recently from 11837fd to bd1eabc Compare July 28, 2022 18:14
As a follow-up to [hotwired#535][] and
[hotwired#546][], add support for declaring custom action
modifiers in the same style as `:prevent`, `:stop`, and `:self`.

Take, for example, the [toggle][] event. It's dispatched whenever a
`<details>` element toggles either open or closed. If an application
were able to declare a custom `open` modifier, it could choose to route
`toggle` events denoted with `:open` _only_ when the `<details open>`.
Inversely, they could choose to route `toggle` events denoted with
`:!open` _only_ when the `<details>` does not have `[open]`.

Similarly, the same kind of customization could apply to custom events.
For example, the [turbo:submit-end][turbo-events] fires after a `<form>`
element submits, but does not distinguish between success or failure. A
`:success` modifier could skip events with an unsuccessful HTTP response
code.

[hotwired#535]: hotwired#535
[hotwired#546]: hotwired#546
[toggle]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement/toggle_event
[turbo-events]: https://turbo.hotwired.dev/reference/events
@seanpdoyle seanpdoyle force-pushed the custom-action-options branch from bd1eabc to d33e66d Compare July 28, 2022 18:25
@dhh dhh merged commit da425c4 into hotwired:main Jul 28, 2022
@seanpdoyle seanpdoyle deleted the custom-action-options branch July 29, 2022 12:14
@seb-jean
Copy link
Contributor

Thank you for this PR.

How could we do with a dialog element to add a custom :open action?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants