You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
value/status/pristine/touched all as observables, individual properties or maybe just all rolled into one observable. And there is always a starting value.
Filters and predicates for types of events
Basically toSignal() version of the stuff from # 1.
(and reset/submitted are possible but kind of edge cases for reasons)
This is a concrete proposal building on a discussion that I opened before: #334. I will refer to this discussion for a link so I do not tag related issues in the Angular GitHub again.
Background to new API before I explain the utility(s) I propose
Edit: @TheIgorSedov just released a great video that explains the API very well with some good graphics and step by step explanations.
Unified Control State Change Events #54579 (see link in above discussion) introduces an observable on forms called events that exposes a stream of events and their respective values. It is targeted for Angular 18, and in my experimentation during release candidates, very useful. I believe that there is room for utilities to be made out of it.
Events + values of those events
value
status
touched
pristine
reset (no value accessor)
submitted (no value accessor)
I think my following proposals mirror existing ngxtension utilities and approaches (injectNavigationEnd and @joshuamorony usage of forms with signalSlice).
My proposal: 3 types of utilities
Observable streams + values
Instance type filters
Signal values
Link to assorted utilities I have made with this new API. Reset/submitted haven't been merged into main yet as those are newer and kind of edge cases. For use cases, you can see some of them used in the main example app component.
These could all have initial values passed into the streams with RXJS's startWith. I will give these examples as versions without that for now.
This was inspired by @joshuamorony's video on using signalSlice and form.valueChanges to subscribe to a form's values to get its state as a signal and do side effects. I have further worked on this since this recent issue #365. That issue is particular to the forms approach with signalSlice and the topic at hand has gotten down to a couple details, but the crux of my proposal is that form observables can make for great events and signals, and this new API exposes a lot we never had until Angular 18.
The generic for events in the unified form events API is of type ControlEvent. To get an event when the form's pristine state changed, it looks like this
form.events.pipe(filter((event: ControlEvent): event is PristineChangeEvent=>eventinstanceofPristineChangeEvent))
An example of an event instance type utility would be a function that does something like the above, but used with this signature:
pristineEvents$=pristineEvents$(this.form).pipe(tap((p)=>console.log('pristine events, map this out or whatever you want',p)));
Since there is 6 event types (and possibly more in the future), it is nice to have them as easy to reference functions. In fact, I use them internally in a later example.
This functionality is somewhat like a simple version of an existing ngxtension utility, injectNavigationEnd. To the extent that filtering for the type NavigationEnd is a bit awkward to do without a utility compared to how useful and common it can be. I don't think this would work like the injectors though, as it has to pass in controls. But these functions do have their own injection context and all that. And all of these utilities would naturally be modified to handle injection contexts and potential leaks.
If it is too granular to have a utility for each of these, I have also made a combined stream that maps out by type. This one does use startWith to get initial values.
Maybe it could be extended to optionally allow for submitted and reset, but those are only events and do not have values and thus would require some initial value or to track other things (Last submitted time? Number of submits? Not sure if it's worth it but it would be different).
Type 2: Type filters
Functions that assert what an event type is, with signatures such as
isPristineEvent(pristine)
Should someone want to grab the whole form.events stream and filter inside with ease. Not as useful in my opinion but it's something possible.
Type 3: Signal values
Naturally, I have toSignaled all of the observables as well. For example:
To always have values, initial values can be passed in to the streams with the RXJS operator startWith. In the equivalent to allEventsUnified$ (which I call $allEventsUnified), all the types of events are combined and passed the respective form.pristine or the other event values.
Igor Sedov made a great video that explains the new events API that this proposal builds on. It covers just about everything I wish I knew about this new form events API before I started making things with it.
I cannot get a Stackblitz going in v18 stable for the life of me. Anyone got one that works? I think there is some issue with node or the newer Angular builders but I was hoping I could demo this on v18 stable by the time it was out.
I guess the 18.0.0-rc1 example is fine for the most part minus the event type name changes and not having submit/reset events.
edit: TL;DR
value
/status
/pristine
/touched
all as observables, individual properties or maybe just all rolled into one observable. And there is always a starting value.toSignal()
version of the stuff from # 1.edit:
Stackblitz: https://stackblitz.com/edit/stackblitz-starters-nbicus?file=src%2Fform-events-utils.ts
PR: #391
(and
reset
/submitted
are possible but kind of edge cases for reasons)This is a concrete proposal building on a discussion that I opened before: #334. I will refer to this discussion for a link so I do not tag related issues in the Angular GitHub again.
Background to new API before I explain the utility(s) I propose
Edit: @TheIgorSedov just released a great video that explains the API very well with some good graphics and step by step explanations.
Unified Control State Change Events #54579 (see link in above discussion) introduces an observable on forms called
events
that exposes a stream of events and their respective values. It is targeted for Angular 18, and in my experimentation during release candidates, very useful. I believe that there is room for utilities to be made out of it.Events + values of those events
I think my following proposals mirror existing ngxtension utilities and approaches (
injectNavigationEnd
and @joshuamorony usage of forms withsignalSlice
).My proposal: 3 types of utilities
Link to assorted utilities I have made with this new API. Reset/submitted haven't been merged into
main
yet as those are newer and kind of edge cases. For use cases, you can see some of them used in the main exampleapp
component.Stackblitz: https://stackblitz.com/edit/stackblitz-starters-nbicus?file=src%2Fform-events-utils.ts
Type 1: Observable events + values
These could all have initial values passed into the streams with RXJS's
startWith
. I will give these examples as versions without that for now.This was inspired by @joshuamorony's video on using
signalSlice
andform.valueChanges
to subscribe to a form's values to get its state as a signal and do side effects. I have further worked on this since this recent issue #365. That issue is particular to the forms approach withsignalSlice
and the topic at hand has gotten down to a couple details, but the crux of my proposal is that form observables can make for great events and signals, and this new API exposes a lot we never had until Angular 18.The generic for events in the unified form events API is of type
ControlEvent
. To get an event when the form's pristine state changed, it looks like thisAn example of an event instance type utility would be a function that does something like the above, but used with this signature:
Usage
Since there is 6 event types (and possibly more in the future), it is nice to have them as easy to reference functions. In fact, I use them internally in a later example.
This functionality is somewhat like a simple version of an existing ngxtension utility,
injectNavigationEnd
. To the extent that filtering for the typeNavigationEnd
is a bit awkward to do without a utility compared to how useful and common it can be. I don't think this would work like the injectors though, as it has to pass in controls. But these functions do have their own injection context and all that. And all of these utilities would naturally be modified to handle injection contexts and potential leaks.If it is too granular to have a utility for each of these, I have also made a combined stream that maps out by type. This one does use
startWith
to get initial values.Maybe it could be extended to optionally allow for submitted and reset, but those are only events and do not have values and thus would require some initial value or to track other things (Last submitted time? Number of submits? Not sure if it's worth it but it would be different).
Type 2: Type filters
Functions that assert what an event type is, with signatures such as
Should someone want to grab the whole
form.events
stream and filter inside with ease. Not as useful in my opinion but it's something possible.Type 3: Signal values
Naturally, I have
toSignal
ed all of the observables as well. For example:To always have values, initial values can be passed in to the streams with the RXJS operator
startWith
. In the equivalent toallEventsUnified$
(which I call$allEventsUnified
), all the types of events are combined and passed the respectiveform.pristine
or the other event values.Signature of
$allEventsUnified
As with the single observable stream, submitted and reset are a bit of an edge case.
The text was updated successfully, but these errors were encountered: