Intermediate workshop
Modern Angular
Master the latest Angular features to build modern applications. Learn how to use standalone components, signals, the new inject method and much more.
The RxAngular team & community were quite productive and shipped great new features as well as quality of life improvements with the latest releases.
We are specifically mentioning the community this time, as we are very happy to anounce that some amazing community contributions made it to this release.
In this blog post, we'll dive into some specifics of RxAngular itself and it's recently added new features, including the native support for signals across its core directives: rxIf
rxLet
rxFor
rxVirtualFor
Intermediate workshop
Master the latest Angular features to build modern applications. Learn how to use standalone components, signals, the new inject method and much more.
Advanced workshop
High-Speed Angular applications on any device
If you don't want to go over all the changes in detail, here is a tiny teaser for you with just the changes being introduced with the latest release.
native signal support
rxLet supports Subscribable (*community contribution)
parent flag deprecation
provideRxStateConfig
expose readonly state (*community contribution)
native signal support
new functional creation method
Before going into details about updates about the @rx-angular/template package
*ngIf
*ngFor
*rxIf
*rxFor
*rxLet
RxAngular directives are optimized for fine-grained reactivity down to the EmbeddedViewRef. This means that only the necessary parts of your template are updated when data changes, leading to better performance.
RxAngular directives allow you to work with context variables and templates in a more intuitive way. This makes it easier to manage complex data structures and logic in your templates.
๐ฃ Conference Talk: Contextual Template States
RxAngular directives support lazy template creation, which can help improve performance by deferring the creation of template elements until they are actually needed.
Users want 60fps and smooth interactions with applications, and RxAngular directives are optimized for this. They ensure that your application remains responsive and performant even when dealing with large amounts of changes by making use of concurrent mode.
๐ฃ Conference Talk: Cut My Task Into Pieces
RxAngular recently introduced seamless integration with Angular signals.
Let's briefly recap what Angular signals are. Signals provide a reactive primitive for managing state within Angular components. They offer a fine-grained and performant way to track changes to values. Thus, angular has an easier time to run change detection only on needed components instead of a sub-tree.
RxAngulars core directives are designed to streamline reactive programming in Angular templates. Now they have been supercharged with signal support. Let's explore how each directive leverages signals to enhance your development workflow:
The rxLet
The rxIf
rxIf
Efficiently rendering lists is a common requirement in web applications. The rxFor
rxFor
rxFor
When dealing with large lists, virtual scrolling becomes essential for maintaining performance. The rxVirtualFor
rxVirtualFor
To start leveraging the power of signals in your RxAngular projects, ensure you have the latest version of RxAngular installed. Then, you can directly use signals with the directives as demonstrated in the examples above.
This was a community contribution, special thanks to Alireza Ebrahimkhani for kickstarting the effort and Adrian Romanski for finishing it off.
Before this version of @rx-angular/template
RxLet
ObservableInput
On top of the Signal
RxLet
Subscribable
Before the introduction of Signal queries (viewChild
viewChildren
contentChild
contentChildren
rxLet
rxFor
This behavior was in most cases just causing overrendering, especially if there were no open queries we had to update.
One could already disable this behavior on a per directive basis via the parent
RxRenderStrategiesConfig
However, as far as we know, this feature is very little known and not used very often.
When disabling the parent
@rx-angular/template
It means that any regular @ViewChild
@ViewChildren
@ContentChild
@ContentChildren
This is also the reason why the default value for this configuration is true
Thanks to the recent additions to the angular framework itself, we can now safely get rid of this flag.
The new Signal queries will just work without having us to additionally run change detection on any level. We can just insert nodes into the viewContainer
It means that any regular @ViewChild
@ViewChildren
@ContentChild
@ContentChildren
Thanks to the new inject method and other additions introduced by the angular framework, we were able to re-think the approach on how to create instances of RxState
RxState
RxState
See the following example:
The instance created by RxState
DestroyRef
Read more about the new functional approach in our migration guide.
We have also introduced native signal support to the RxState
RxState
Signal
Additionally, we've introduced a new overload for connect
Signal
You'll find more information about this in the getting started guide.
Users of RxState
RxState
Let's dive into the details.
Configurations for RxState
provideRxStateConfig
By default, RxState
queueScheduler
withScheduler()
withSyncScheduler()
The queueScheduler provides a certain level of integrity, as state mutations that cause other state mutations are executed in the right order.
"When used without delay, it schedules given task synchronously - executes it right when it is scheduled. However when called recursively, that is when inside the scheduled task, another task is scheduled with queue scheduler, instead of executing immediately as well, that task will be put on a queue and wait for current one to finish."
"This means that when you execute task with queue scheduler, you are sure it will end before any other task scheduled with that scheduler will start."
_src: queueScheduler on rxjs.dev
In conclusion, it is possible that you can run into the situation where a state mutation isn't synchronous.
See the following very simplified example:
In order to escape this behavior, you can define the scheduling to be fully synchronous:
It is however also possible to define whatever SchedulerLike you want, e.g. make your state asynchronous by using the asapScheduler.
The accumulator defines how state transitions from change to change and how slices are integrated into the state.
By default, RxState
AccumulatorFn
The AccumulationFn
reducers
You can now use the withAccumulator
AccumulatorFn
This was a community contribution, special thanks to Adrian Romanski for implementing this feature.
If you only want to expose your RxState
asReadOnly()
Thanks for reading this long post and we hope these new features will be useful for you and your team.
If you haven't yet, go and leave a โญ for us on github!