Honestly, they haven’t brought a lot of features into a single major version for a while, so the community seems to be thrilled and looking forward to it.
In this article, we’ll see the features of Angular 14. Here are the features that I am going to talk about.
It’s crystal clear that the community is getting bored with NgModules even if there are few people in love with them. Since Angular 14, we will be able to develop an application without any modules even and even AppModule.
Let’s create a new Angular 14 app and see how standalone components work.
To create that, run the following command;
npx @angular/cli@next new standalone-playground
The next step is converting
AppComponent into a standalone one, so when your application is created, update the
main.ts as below;
Then delete the
Then quickly update
app.component.ts and mark it as standalone
Now we need to import Angular Router and define the routes. That was already done in
app.module.ts but we just deleted that.
Since Angular 14, we can import providers in
As you can understand from its naming,
importProvidersFrom() function extracting providers from NgModules and moduleWithProviders.
Lastly, to make
router-outlet directive work, we should import
RouterModule in our
AppComponent, so we should update it as following;
Now, our application should be working fine with an empty route config. Before deeply diving into route config, let’s create another standalone
TitleComponentand use it.
To create a new standalone component, we can use a built-in Angular schematic;
ng generate component title --standalone
When you run the command, you will discover that it didn’t change anywhere else. It just created
html/<style>/ts/spec.ts files. Welcome to the world without
Then, we can proceed with
TitleComponent is ready to use!
Finally, we can start using it by updating
We must import all of the modules and dependent components/pipes/directives into the standalone component, so let’s import
Yay! Everything is working fine! Congrats, you have created standalone components, and you know how it works!
Before moving to the Router configuration, let’s create three new standalone components named
Now we are ready to dive into the Router configuration deeply. We left that as an empty array before, so we should fill that.
We will configure 3 different paths on our root level router configuration.
'home' => Eager Load - HomeComponent
'contact-us' => Lazy Load - ContactUsComponent
'about' => Lazy load - sub-routes.
Let’s go step by step and update the configuration accordingly.
Since it’s an eager loaded path, there are no changes. We can just configure that as we used to.
Instead of using
loadChildren, we are going to use
loadComponent property to lazy load standalone component.
As you can see, we directly referred
ContactUsComponent instead of a module.
We will use
loadChildren property. Since there are sub-routes on
about path we will import the sub-routes instead of
To sum up, we have not defined any
NgModule even though we have 3 routes. That is how standalone components work.
More Powerful Dependency Injection
Angular 14 will be a game changer for dependency injection. The great news is that we will be able to use the
inject()in components, directives, and pipes, and thus we can create reusable functions which use dependency injection.
Let’s see what we were doing before Angular 14 to create a new subscription that needs to be destroyed.
Thanks to the
inject(), we can get rid of the
ngOnDestroy lifecycle and destroy the subscriptions by creating a new Rxjs operator. See the example below.
We created a reusable Rxjs operator named
takeUntilDestroy$ and automatically destroyed our subscription by using that.
Unfortunately, we have a limitation while using
The inject function has to be called in injection context
That means that if we move the
takeUntilDestroy Rxjs operator to the
ngOnInitlifecycle, it will not work. It must be registered during construction, so it will not be allowed to inject something depending on the component’s input parameters.
We were using
@Directive() decorator to take advantage of dependency injection in abstract classes. As you may know, an abstract class with the decorator can make an injection. However, if we need to have some additional injections, we must type
constructor() and pass required injections by
Thanks to the
inject() we can get rid of it. Let’s see what we were doing before Angular 14 and what we can do with it.
Page Title Resolver
I guess most of the Angular developers implemented their own fancy page title handling functionality. We were using router events, and once the navigation was completed, we read route data and set it as the title.
Finally, Angular Team has published a built-in and great solution for that. We will have a
title attribute on the route config, and once the router hits the route, it will automatically update the title. Additionally, we can use a resolver to grab data to generate the title,
Last but not least about the feature, we have a new InjectionToken named
TitleStrategy that allows us to manipulate the title. For example, we can prefix the company name to the route title.
We already know that we can get rid of all NgModules thanks to the standalone components, but what about the providers? How will we provide something?
Angular 14 allows us to add providers into the router config. It’s pretty easy, and they will be provided once a user hits the route.
As you can see on the code, we have provided 2 different values for about and home paths so that
HomeComponent will print
AboutComponent will print
Sometimes, we may need to call a method on a service when a lazy module instance is created or the application is bootstrapped. We used to use dependency injection in a module to create an instance of a service.
Imagine that you have a
ActivityLoggerService which logs router events, so the solution before v14 is creating a module below and calling the
listen() method of the service in the
Thanks to the environment initializer, we don’t need to use the tricky way to call
listen(). Here you can see the same implementation with the environment initializer feature.
If we need to call that when a user hits a lazy loaded route, we can simply provide it as a route provider.
Typed Reactive Forms
Eventually, Reactive Forms will be type-safe with Angular v14. As you already know, it has no type-safe implementation, so we were dealing with the typo issues in our reactive forms. Let’s move to the details by an example.
Imagine that you have the following reactive form on your Angular 13 project.
When you run
ng update command to migrate your application to Angular 14, your form will be changed as the following.
The schematic replaced
UntypedFormBuilder, so we can understand that our
FormGroup is still not type-safe. Let’s convert it into a type-safe by creating an interface and marking the
We marked the form control named
website as optional, so it’s allowed to be removed. On the other hand, we cannot remove the control that is not optional.
Passing an Injector to Embedded Views
One of the fancy features of Angular 14 is that we are allowed to create a new injector and pass it to the embedded view, so we will be able to bring new providers into a new injector.
Angular CLI Autocomplete
Angular CLI will provide real-time type ahead auto-completion. You can just type
ng and press TAB. It will show all possible commands with descriptions. Enter to choose one.
It looks like Angular v14 contains a lot of useful updates. Since it is still not released, the features may be changed. I will keep the article up-to-date until the official release.
If you have questions, feel free to contact me.
See you in another article!