Closed michael-small closed 2 months ago
I edited this into the issue about as well, but this is so good I want to highlight it here as well: https://www.youtube.com/watch?v=v7r-7PHaEtY
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: context: https://x.com/MichaelSmallDev/status/1794451615916917059
1) You can upgrade a v17 project to v18 using ng update 2) There is a pending PR on Stackblitz side for Angular 18.0 support
edit 2: made a starter for Angular 18 + Material, will make example of these form utils without Material sometime later https://stackblitz.com/edit/stackblitz-starters-o2heai?file=package.json
edit: TL;DR
1)
value
/status
/pristine
/touched
all as observables, individual properties or maybe just all rolled into one observable. And there is always a starting value. 2) Filters and predicates for types of events 3) BasicallytoSignal()
version of the stuff from # 1.edit: Stackblitz: https://stackblitz.com/edit/stackblitz-starters-nbicus?file=src%2Fform-events-utils.ts PR: https://github.com/ngxtension/ngxtension-platform/pull/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: https://github.com/ngxtension/ngxtension-platform/discussions/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 https://github.com/ngxtension/ngxtension-platform/issues/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.