-
Notifications
You must be signed in to change notification settings - Fork 424
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
Feature request - Event when Stimulus connects to an element #701
Comments
I was looking into this the other day and I agree that there are some good use-cases for this. One of them was when looking at #698 as you already pointed out. But I can also see those events to be helpful for proceeding with #687 / #690. In that case I'd even argue that a |
Thinking about edge cases here : what would be the desired behaviour when there are multiple controller instance on a single page ? do we fire multiple events? Or one event when all controllers are loaded? also for the naming, I would suggested initialised/connected |
@adrienpoly for the multiple controller instances, I would envisage that for each controller's connection there would be a different event fired. If you wanted you could just However, based on the above comments, here is a revised proposal. Lifecycle eventsA new feature in Stimulus that can be used to automatically trigger custom DOM events based on key application and controller lifecycle methods.
The Stimulus application schema would be updated with a new inner object, The default of which would be structured as follows; name: 'application', // or Stimulus?
events: {
// application lifecycle events
startBefore { auto: true, name: 'starting' }, // called beforethe application instance has started, prefixed with the schema's application name (e.g. `'application:starting'`), dispatched on `window` with the application instance accessible in the event's detail, can be cancelled?
startAfter: { auto: true, name: 'started' }, // called after the application instance has started, prefixed with the schema's application name (e.g. `'application:started'`), dispatched on `window` with the application instance accessible in the event's detail.
stopAfter: { auto: true, name: 'stopped' }, // called after the application instance has stopped, prefixed with the schema's application name (e.g. `'application:stop'`), dispatches on `window`.
// controller registration lifecycle events
shouldLoad: { auto: false, name: 'load' }, // cancellable, if event.preventDefault is called, behaves similar to the `shouldLoad` static method on a controller returning false, prefixed with the controller's identifier and has access to the `controllerConstructor` in the event detail.
loadBefore: { auto: false, name: 'registering' }, // when a controller is about to be registered, can be cancelled? dispatches on `document`, event detail will have access to the `controllerConstructor`, prefixed with the controller identifier. Note. Maybe this and the above shouldLoad event can be merged into one. An event before any registration, even before shouldLoad is called & can be cancelled.
loadAfter: { auto: false, name: 'registered' }, // after the controller has been registered and after `afterLoad` has resolved/completed, dispatches on `document`, event detail will have access to the `controllerConstructor`, prefixed with the controller identifier.
// controller instance lifecycle events
connectBefore: { auto: false, name: 'connecting' }, // before the connect method on a controller instance is called, dispatches on the controlled element, prefixed with the controller's identifier.
connectAfter: { auto: false, name: 'connected' }, // after the connect method on a controller instance has resolved/completed, dispatches on the controlled element, prefixed with the controller's identifier.
disconnectBefore: { auto: false, name: 'disconnecting' }, // before the disconnect method on a controller instance is called, prefixed with the controller's identifier.
disconnectAfter: { auto: false, name: 'disconnected' }, // after the disconnect method has resolved/completed, dispatches on `document`, prefixed with the controller's identifier.
// controller instance target lifecycle events
// maybe one day - YAGNI for now (targetConnectBefore, targetConnectAfter, detail contains the target name, dispatched on the first target element that is part of that microtask).
} By default, only the application start/stop events will be fired, this will be mostly opt-in, but this could change in a future release. Additionally, the ability to cancel some events could be brought into later releases if needed. This provides a way to set the The event names cannot be altered any other way aside from the schema but additional opt-in/out can be set up at the Controller level. Controller
|
A potential better name for this could be
It may also be simpler to avoid the whole part of the schema setting the default opt in stuff. Instead, each controller just opts in, the event names would still be declared in the application schema. This aligns with the idea of Controllers being easily isolated/reused. |
Found about this issue because when doing e2e tests with lazy controllers you have to wait for them to be loaded. I would have added such controllers’ element an HTML attribute on For now it doesn’t seem like it is possible to do it in a decoupled way: you have to update every concerned controller. From what I understand the feature requested here would allow for doing this by adding a single listener. Is it still considered? |
Problem
I find myself writing, in various forms, controller code that allows some action to be dispatched when a controller connects.
This method could be manually called in the connect method, but sometimes it's more appropriate to have this call made optionally depending on usage. We could add a value to 'do thing on init', but writing an additional action feels more appropriate and makes more sense.
Example
As its simplest, the code often looks like this...
Proposal
Every controller, when connected would dispatch two events on the controlled element by default. These two events would bubble, are not cancelable and their prefix can be configured using the Stimulus schema.
init:my-controller
- dispatched before the connect method callback is called. Less critical.ready:my-controller
- dispatched after the connect method has completed. If the connect method is Async /returns a promise it will only dispatch when that has resolved successfully.Note: Originally, I had suggested these events should not bubble but it may make sense to have this bubble and allow them to be restricted by the
self
event filter.This also sets up a way to do a global event listener, per controller identifier, to hide something until ready. E.g. a data attribute or class that gets removed when the ready event is dispatched.
Example new usage
We no longer need the overhead in our controller...
Additional references
init
https://alpinejs.dev/essentials/lifecycleload
trigger https://htmx.org/attributes/hx-trigger/The text was updated successfully, but these errors were encountered: