
In our job, it’s very challenging to follow the continuous evolution of the frameworks and development tools. In this article, we will see what’s new in Angular 9, why it is a remarkable version, and why it is worthful test it as soon as possible.
The expected release date for the ninth version was November 2019, but the official announcement by Stephen Fluin arrived only on February 6th. There were a lot of criticisms, maybe due to the natural diffidence around the Angular team, heir of that dramatic transitioning from Angular.js to version 2.0.
Before going into the details, please note that in this article I will use version 9.1, published on March 26th.

Version 9 is relevant because it introduces, by default, Ivy, a new pipeline for compilation and rendering (available for testing also in version 8).
Why this rewriting? First of all, a big part of web traffic comes from smartphones and tablets. The main challenge for a front developer is to load a web application as fast as possible, taking into account the volatility of an internet connection. The first step is to reduce the bundle size produced by the framework. The Ivy compiler has been designed to remove parts of Angular that aren’t being used via tree-shaking and to generate less code for each Angular component. Small apps and large apps can see the most dramatic size savings while medium-sized apps should see bundle sizes that are only slightly smaller.

The new Debug experience
Let’s create a new project using the ng new command and the –minimal option that removes all the files necessary for the testing.
ng new my-first-demo--minimal --style=css
Let us suppose to have a father component called ProductListComponent and its son called ProductDetails. Starting from this situation, let’s see how the debug experience in Angular changes using the Chrome developer tools. Select our father component in the Components panel, and let’s move to the console.

Inside the console, we can access a new object called ng, designed to improve the debugging experience. Let’s start associating a variable to the selected component, available through the $0 alias. The ng api returns the component with ng.getContext($0).

We can clone the first product, modify it, show the differences with a console.table

and, finally, invoke ng.applyChanges($0) to force the change detection in Angular. We can also invoke the methods of the selected component to emulate the click on a button.

Type checking
Typescript allows us to find the type errors inside the code but, till now, the templating missed such strong support. Inside the tsconfig.json file, there is a flag called fullTemplateTypeCheck that in Angular 9 is set to true while the false value triggers the basic type-checking mode. Let’s consider the following case:
<app-product-details
[store]="user.address.city" [product]="selectedProduct">
</app-product-details>
The compiler checks that:
- user is a property belonging to the class component
- user is an object with the address property
- user.address is an object with the city property
In the basic type-checking, the compiler does not verify that the value of user.address.city is assignable to the input called store inside the child component. Besides, the so-called embedded views, for example, *ngIf, *ngFor, and ng-templates are not checked. Either the results of pipes and the type of $event in event bindings are not checked.
When the fullTemplateTypeCheck flag is set to true, Angular applies a more rigorous type checking. Embedded views are checked, pipes have the correct value type and local references to directives and pipes have the correct type.
Let’s consider an *ngFor:
<div *ngFor="let product of products">
<h3>{{config.title}}</h2>
<span>Store: {{user.address.city}}</span>
</div>
In basic mode, <h3> and <span> are not checked. In full modality, instead, the compiler checks if config and user exist, but it assumes any type for them!
Angular 9 introduces a third check modality called strict mode. With it, the framework defines that user inside the span has a User type, and that address is an object with a string property called city.
The strict mode is accessible only with Ivy, setting tsconfig.json like this:
"angularCompilerOptions":
{
"strictTemplates": true,
"strictInjectionParameters": true
}
In the following example:

I intentionally changed the case for the Id property that is id in the interface definition. Leaving the tsconfig.json in the original version
"angularCompilerOptions":
{
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
the ng build compilation successfully passes.

Passing to the strict mode, instead, the compilation fails.

AOT compilation
Used to launch our apps with the ng serve command, how many times we discovered build errors as we were ready to go to production, executing the ng build –prod command? It was happening that this last option has started the AOT (Ahead of Time)
Why we need a compilation? What is compiled? When does this compilation happen? We can invoke the Angular compiler at runtime (in the user browser) or at build time in the build process. It has always been said that Angular is portable: it can be executed on every platform with a Javascript VM.
In the first case (Just-In.Time Compilation) the typical flux is:
- development of code in Typescript
- compilation with tsc
- bundling, minification and deployment
The user open the app in her/his browser starting the following steps:
- the download of all the Javascript assets
- the bootstrap of Angular
- the generation of the Javascript for each component in the application
- the rendering of the application
In the Ahead-Of-Time compilation instead we have the following steps:
- development of code in Typescript
- compilation with ngc
- bundling, minification and deployment
What happens instead when the user open the app in her/his browser is:
- the download of all the Javascript assets
- the bootstrap of Angular
- the rendering of the application
The user experience is better and faster because a more efficient Javascript code is generated in the build phase, and the browser needs only to render the page. The details of how the AOT compilation works are behind the scope of this article, but I must confess that I find this world truly fascinating. With Angular 9, the AOT compilation with Ivy is so fast and efficient that now it is used even with ng serve for the builds in the developing phase!
Dependency Injection (DI)
Other significant news concerns the Dependency Injection. DI is cabled inside Angular and used everywhere to provide all the components with the services they need. The Angular components consume services injected through the constructor.

Any class can be a service. If we precede its definition with a @Injectable() decoration, we can modify the default metadata necessary to Angular to inject it into a component as a dependency. @Injectable() is also needed to mark that a class has its own dependencies.
In its bootstrap phase, Angular creates an injector available to the whole application. The injector creates the dependencies and manages, inside a container, all the instances of the dependencies to reuse. Finally, a provider tells the injector how to obtain or create a dependency.
Let’s consider the following example showing the constructor of a component:
constructor(private service: ProductsService) { }
When Angular discovers that a component depends on a service, first of all, it checks if the injector has an available instance of that service. If there is not, the registered provider creates it and adds it to the container before passing it to the component.
Every service needs at least one provider registered at the application level. Such a provider may be put inside the metadata of the service (the @Injectable() decorator), and in such circumstance, the service is available everywhere in the application. Alternatively, we can register the provider at the module or component level (inside the @NgModule or @Component metadata).
By default, the Angular CLI with the command ng generates registers a provider with the root injector, meaning that a single shared service instance is created and injected into any class requesting it.
@Injectable({
providedIn: 'root'
})
The root injector has another advantage: it removes such an instance if it is never used in any component. Inside a specific module, we can register a provider providing the same instance to all the components inside that module.
@NgModule({
providers: [
ProductsService
],
...
})
When we register a provider at the level component, we create a new instance of the service for each new instance of the component.
@Component({
selector: 'app-products-list',
templateUrl: 'products-list.component.html',
providers: [ProductsService]
})
With Angular 9, when we create an @Injectable() service, we have two new options for providedIn: platform and any. According to the documentation, the platform option makes a service available as a singleton with an injector that is shared among all the applications on a page. Don’t forget that your SPA index.html page may result in principle host more than one Angular application! In such a way, we succeed in sharing a service surmounting the famous and insuperable application boundaries!
The providedIn: any option works like this: service will be provided in every module in which it is used. Any lazy-loaded module (another important feature available since Angular 8) has its instance of the service. Instead, the modules loaded as usual (eager modules) will continue to share the single instance provided by the root module injector. This new option available for the lazy-loaded modules was designed to avoid side-effect interferences between modules.
Lazy-Loading Components
We are used to thinking of modules as first-class citizens, even as the most important block in an Angular application. In a module, we declare the components, the directives, pipes, and services. An application can’t exist without a module, but Ivy starts from a different approach: a component may exist without a module. This concept is called locality: every necessary metadata is local to the component.
Let’s use the ng CLI to generate a component called FirstLazy using the following options:
ng g c first-lazy --flat --skip-import --skip-selector
We have a single file in which is declared the FirstLazyComponent class without even a selector.
import { Component} from '@angular/core';
@Component({
template:
<p>
first-lazy works!
</p>
`
})
export class FirstLazyComponent {
constructor() { }
}
The component we created is not even registered in the root module (app.module.ts).
How can we load it? First of all, let’s insert a button in the AppComponent with a function associated with the click event.
@Component({
selector: 'app-root',
template: `
<div>
<div>My first lazy component </div>
<button class="btn btn-info" (click)="showLazy()">Create</button>
</div>
`
})
export class AppComponent {
title = 'my-first-demo';
showLazy(){
}
}
In the constructor, we can inject an instance of ViewContainerRef. It is a container in which we can add one or more views to a component. We inject another service called ComponentFactoryResolver that allows us to create a component by code.
export class AppComponent {
title = 'my-first-demo';
constructor(private cfr: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef) {
}
showLazy(){
}
}
In the showLazy() method, first of all, we empty the container from the presence of eventual components. Then we import the component code asynchronously and create it using the ComponentFactoryResolver.
async showLazy(){
this.viewContainerRef.clear();
const { FirstLazyComponent } = await import('./first-lazy.component');
this.viewContainerRef.createComponent(
this.cfr.resolveComponentFactory(FirstLazyComponent)
);
}
We have an alternative that gives us significant control over the container. We use an ng-container in which we define a template reference variable
template: `
<div>
<div>My first lazy component </div>
<button class="btn btn-info" (click)="showLazy()">Create</button>
<div class="myBackground">
<ng-container #myContainer></ng-container>
</div>
</div>
In the code we use the @ViewChild annotation and we set it in a way that ViewContainerRef points to our #myContainer. Then we modify the method:
export class AppComponent {
title = 'my-first-demo';
@ViewChild('myContainer', {read: ViewContainerRef}) myContainer: ViewContainerRef;
constructor( private cfr: ComponentFactoryResolver) {}
async showLazy(){
this.myContainer.clear();
const { FirstLazyComponent } = await import('./first-lazy.component');
this.myContainer.createComponent(
this.cfr.resolveComponentFactory(FirstLazyComponent)
);
}
}
In the code of our lazy component we can insert a property (I called it message), then create an instance passing as a parameter an injector injected in AppComponent. In this instance, we can set the message property using a service of ours (ProductsService).
export class AppComponent {
title = 'my-first-demo';
@ViewChild('myContainer', {read: ViewContainerRef}) myContainer: ViewContainerRef;
constructor(private cfr: ComponentFactoryResolver,
private injector: Injector,
private myservice: ProductsService) {
}
async showLazy(){
this.myContainer.clear();
const { FirstLazyComponent } = await import('./first-lazy.component');
const {instance} = this.myContainer.createComponent(
this.cfr.resolveComponentFactory(FirstLazyComponent), null, this.injector);
instance.message = this.myservice.message();
}
}
We can check in the network activity how the component was lazy-loaded.

A lazy-loaded component can load other lazy-loaded components as children. The scenario we aim to is to manage our application’s features without the routing. Why should we do it? I would say to have greater control over the loading in high-consuming resources application.
Eventually, our lazy-loaded component will need external modules (let’s think to Material, for example). How can we add these modules? We can’t use our AppModule to load them eagerly, because we will produce an error:
error TS-998001: 'mat-card' is not a known element:
1. If 'mat-card' is an Angular component, then verify that it is part of this module.
2. If 'mat-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
The solution is to add to the component file a little module without export declarations. This module will declare only one component: FirstLazyComponent.
@NgModule({
declarations: [FirstLazyComponent],
imports: [CommonModule, MatCardModule]
})
class MyLazyModule {
}
This trick is necessary because now we need a module to import other modules. This will not be true in future Angular versions. The Angular’s future will be based on Ivy and the concept of locality: a component will be completely self-contained.
I hope you liked the new Angular features and that you will use them as soon as possible. The article code is available at the following address.
See you next time!