What's new in Angular 9

About me
-
Senior Frontend Developer @
-
Creator of DevNote
Nutti Saelor (Lee)



Ivy is here!

Ivy
- 3rd Generation Rendering Engine
- Complete Rewritten
- Tree Shaking
- Locality

Credit: Ivy A deep dive into the heart of Angular by Martina Kraus https://t.co/Z1M3TIWzL4?amp=1

Credit: Ivy Renderer for Dummies by Gerard Sans https://slides.com/gerardsans/components-conf-ivy-renderer#/
<div class="greeting">
Hello, world!
</div>
View Engine


Ivy


Locality

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Locality

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Lazy Component

Credit: Angular's Future with Ivy by Manfred Steyer https://speakerdeck.com/manfredsteyer/angulars-future-with-ivy

Smaller
Smaller

Credit: Angular Connect Day 1 Keynote https://g.co/ng/ac2019
Smaller

Credit: Suguru Inatomi Twitter https://twitter.com/laco2net/status/1193726958284111874
Smaller

Credit: Suguru Inatomi Twitter https://twitter.com/laco2net/status/1193730598319210496
Faster Compilation
Faster Compilation

Angular 8.3
Faster Compilation

Angular 9.0 RC4
Improved Type Checking
Improved Type Checking
- Basic Mode: To enable set fullTemplateTypeCheck: false
- Full Mode: To enable set fullTemplateTypeCheck: true
- Strict Mode: To enable set fullTemplateTypeCheck: true and strictTemplates: true
Improved Type Checking
// tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
...
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictTemplates": true
}
}
Improved Type Checking
Basic Mode
- Validate only top-level expression
- Don't check embedded view (*ngIf *ngFor ng-template)
- Don't figure out the types of #ref, results of pipes, type of event
Improved Type Checking
Full Mode
- More aggressive in its type-checking within templates ex. Embedded view are checked, pipes have correct return type, Local references(Directive/Pipe) have correct type
- Local references to DOM, $event object still have type any
Improved Type Checking
Strict Mode
- Verifies that component/directive bindings are assignable to their @Input()s
- Infers the correct type of components/directives, including generics
- Infers the correct type of $event
- Infers the correct type of local references to DOM element
Improved Type Checking
interface User {
name: string;
address: {
city: string;
state: string;
}
}
<div *ngFor="let user of users">
<h2>{{config.title}}</h2>
<span>City: {{user.address.city}}</span>
</div>
How to update?
How to update?

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Backward Compatible
Backward Compatible

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Backward Compatible

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Backward Compatible

Credit: The Post-Ivy World by Minko Gechev https://t.co/XOT3n8rQYd?amp=1
Backward Compatible
Opting out of Ivy
// tsconfig.app.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [ ...],
"include": [
"src/**/*.d.ts"
],
"angularCompilerOptions": {
"enableIvy": false
}
}
Ivy Compatible Guide
Other updates
Clipboard CDK
<button cdkCopyToClipboard="👋 You copied me!">Click to copy</button>
constructor(private clipboard: Clipboard) {}
copyId(id: string) {
this.clipboard.copy(id)
}
Google Maps Component
<google-map
height="500px"
width="100%"
[zoom]="zoom"
[center]="center"
[options]="options"
(mapClick)="click($event)"
>
<map-marker
#markerElem
*ngFor="let marker of markers"
[position]="marker.position"
[label]="marker.label"
[title]="marker.title"
[options]="marker.options"
(mapClick)="openInfo(markerElem, marker.info)"
>
</map-marker>
<map-info-window>{{ infoContent }}</map-info-window>
</google-map>
Default Value for static flag
@ViewChild(ChildDirective) child: ChildDirective;
@ViewChild(ChildDirective, { static: false }) child: ChildDirective; // similar to above code
TypeScript 3.6 Support
Deprecated
Deprecated
Replace TestBed.get with TestBed.inject
TestBed.get(ChangeDetectorRef) // returns any
TestBed.inject(ChangeDetectorRef) // returns ChangeDetectorRef
No more entryComponents
@NgModule({
imports: [MatDialogModule],
declarations: [AppComponent, ExampleDialogComponent],
entryComponents: [ExampleDialogComponent],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
Future with Ivy
*with experimental API
Higher Order Component

Credit: Angular's Future with Ivy by Manfred Steyer https://speakerdeck.com/manfredsteyer/angulars-future-with-ivy
Higher Order Component
const routes: Routes = [
{
path: 'comic/:comicId',
component: withRoute(ComicComponent)
}
];
Optional NgModule
import {Component, Input, ɵrenderComponent as renderComponent, Pipe, ɵmarkDirty as markDirty} from '@angular/core';
import '@angular/compiler';
@Component({...})
class ChildComponent { ... }
@Pipe({ name: 'capitalize' })
class CapitalizePipe { ... }
@Component({
selector: 'app-cmp',
template: '<zippy title="Toggle">{{ label | capitalize }}</zippy>',
deps: [ChildComponent, CapitalizePipe]
})
class AppComponent {
label = 'hello world';
}
renderComponent(AppComponent);
Credit: angular-ivy-demo by Minko Gechev https://github.com/mgechev/angular-ivy-demo
Zone less Application
import {Component, Input, ɵrenderComponent as renderComponent, Pipe, ɵmarkDirty as markDirty} from '@angular/core';
import '@angular/compiler';
@Component({
selector: 'zippy',
template: `
<button (click)="toggle()">
{{title}}
</button>
<div [hidden]="!show">
<ng-content></ng-content>
</div>
`,
})
class ChildComponent {
@Input() title: string;
show = false;
toggle() {
this.show = !this.show;
markDirty(this);
}
}
...
Credit: angular-ivy-demo by Minko Gechev https://github.com/mgechev/angular-ivy-demo
Q&A
Thank you!
What's new in Angular 9
By Lee Lorz
What's new in Angular 9
- 2,041