What is new in Angular 14.2?
We did talk about Angular 14.0 before, but there are new features to discuss thanks to the hard work of Angular Team. They made Angular 14 much more efficient by including new fancy features.
If you haven’t checked the features of Angular 14, I highly recommend you read my related article first.
In this article, we’ll see the features of Angular 14.2. Here are the features that I am going to talk about:
CanMatch Guard
We have a new guard called CanMatch
which is released with Angular 14.2. It decides whether the route is matched or not. If all of the registered CanMatch
guards return true, the router proceeds to load the route. If at least one of them returns false, it tries to find another matching configuration.
In the following example, we have two route configurations. One is for admins and the other is for users. We are going to create a CanMatch
guard that decides whether a user's spec and path match or not.
In this example, the router checks configurations one by one. First, it matches the dashboard path which renders AdminDashboardComponent
and runs the MatchAdminGuard
. If it returns false, it will scan the rest of the configurations by starting with the next one which renders UserDashboardComponent
.
CanMatch
guards can return UrlTree
just like the other guards. If one of the guards returns a UrlTree
, it directly navigates to the generated path.
Inline Guards and Resolvers
Guards and Resolvers can be an inline function instead of a class. It’s nice to have just a single line of code instead of creating a new class that implements something etc.
For example, we can quickly get rid of MatchAdminGuard
and make it inline.
Standalone CommonModule Pipes/Directives
Directives and Pipes exported by CommonModule
are standalone now. Thus, we can now import those classes into our components and modules instead of the whole module.
You may already know NgIf
directive is defined in CommonModule
and we had to import it to use. As you can see in the example below, we can now directly import NgIf
standalone directive into a component.
Environment Injector
As you may remember from Angular 14.0 we are able to use inject()
function in components, directives, and pipes. And it had a restriction to be called in the injection context as we discussed before. (Check here)
Now Angular introduced a new class called EnvironmentInjector
. Thanks to that we are able to make an injection wherever we want. They expect this functionality to be very useful for designing ergonomic APIs.
First, we need to know the definition of environment
. We can simply call it as NgModule
, so we can consider the environment injector keyword as NgModuleRef
injector.
There is something we need to not forget.
EnvironmentInjector
is completely independent from Component tree. It’s a module injector, so it can’t inject anything that is not in module or router.
See the example below;
Example of Environment Injector in Lazy Modules;
As you can see, injected values are different for injector
and environmentInjector
, so they are not the same.
Lifesaver Providers
We needed to extract the providers from NgModules
. Thanks to built-in importProvidersFrom
method we were easily appending them. However, it was confusing people.
You may be used to the following code block we were using when the root component is standalone.
The confusing thing here is the importProvidersFrom
function. Unfortunately, we need it as we are trying to add NgModules
to the providers array. The function extracts the providers that are defined in NgModule
and returns them. Eventually, we have new built-in functions to get rid of importProvidersFrom
method.
I am sure that we are gonna have new ones in future.
Optimized Images
Angular now implements performance improvements automatically for us. It warns us of whether an image needs to be prioritized and there is no preconnect
tag in the head
element of the document and more.
At first glance, it may look tough to understand but let’s follow the instructions that Angular provides and see.
To use it, we need to import the directive and replace src
attribute with ngSrc
and provide at least width
and height
.
Width and height attributes are required because they prevent image-related layout shifts.
Let’s start by providing width
, height
and ngSrc
When I try to render the component, Angular warns me about improvements that need to be done.
Let’s focus on the first one. It says I provided the width
and height
wrong. Let’s fix that by changing them to provide the correct aspect ratio.
The first one is okay and the warning has gone away.
The second one says that the image is an LCP element but not prioritized. Let’s add the priority
attribute quickly.
We had 2 warnings and all good now. Let me check the developer console one more time.
Errr, we have a new one…
It says there should be a preconnect
tag in the head
element of document
. Let’s do whatever it says by adding the following line to index.html
.
<link rel="preconnect" href="https://aurora-project.imgix.net" />
It wouldn’t be funny to see it warns of something else right? 😤
Luckily, nothing else. It’s okay and working fine now.
Well. What else we can do with this directive? Let me explain the input parameters one by one.
Moreover, it supports various image loaders for third-party image services. That means we can provide a loader for the services below.
Thanks to this feature, we can refactor our code and start using Imgix
loader. Let me add ngSrcset
property to let Angular generate srcSet
property for me.
If you haven’t heard what srcSet
is I recommend you to check here.
Note: Base64 and blob images are not supported by the directive.
I know, it may look confusing but Angular guides developers well by telling us exactly what we need to do. Don’t be scared; just start using! 🚀
FormRecord
FormRecord
is very similar to FormGroup
. Moreover, when I check the source code, I discovered that it directly extends from FormGroup
. The only difference is that it can be used with dynamic keys and all of the controls need to be of the same type.
More Useful NavigationError Event
Previously, we were not able to reach ActivatedRoute
in NavigationError
, so there was no way to reach the route data when it fails.
Imagine you have an injectable that listens to router events to take an action when navigation fails.
Here is the NavigationError
class before Angular 14.1
Here is what we have now;
And it now includes RouterStateSnapshot
that includes routes inside, so we can more easily determine which navigation failed including the matched Route
configs for the navigation.
Note: It’s nullable because the error could have occurred before
RouterStateSnapshot
was created.
Conclusion
As we discussed, fancy features have been released without a major version upgrade. That got me excited to see the features of Angular 15 which will be released in November.
See you in November then!
GitHub Repository for Examples
You can clone the repository below and switch between branches to play with examples for each functionality.
BONUS:
Angular announced that standalone components are going to graduate from Developer Preview in Angular 15. 🚀