What's new in Angular 13?
Angular 13.0.0 is here!
This new major version contains a few changes, and the Angular team also published a few RFCs about the future of Angular, that we discuss at the end of this post.
Typescript 4.4, RxJS 7, NodeJS 16 support
Angular 13 requires your code to be written in Typescript 4.4, and dropped the support of TS 4.2 and 4.3. Angular now also officially support RxJS v7, so you can upgrade your applications in peace (but Angular itself still uses RxJS v6 internally). The NodeJS versions from v12.20+ to v16.10+ are now supported.
The update to TypeScript 4.4 removes the need for Angular to workaround
a limitation of TypeScript which did not allow a setter to have a different type than its getter.
So until now, if you wanted a component to accept a boolean or a string for an @Input()
setter, and the getter to only return a boolean, you had to use the weird “input type coercion” syntax with:
@Input() get disabled(): boolean { return this._disabled; }
set disabled(value: boolean) { this._disabled = (value === '') || value; }
// ngAcceptInputType is a hint for the Angular compiler to know that the input
// can in fact be a boolean or a string
static ngAcceptInputType_disabled: boolean | string;
This can now be removed as TypeScript supports a different type for the getter/setter pair \o/. There are no migration or warning messages for this change, so you’ll have to search for ngAcceptInputType
yourself.
IE11 support dropped
Angular dropped support for IE11, and code specific to this browser is starting to be removed from the framework and the CLI. Hopefully this shouldn’t be a problem for you, as IE11 is now something like 0.5% of the market share, and even big companies like Google don’t support it anymore. The CLI will now output a warning message if you’re still trying to build for IE11.
View Engine end-of-life
It’s official, View Engine is no longer supported, and the code will slowly disappear from the framework.
As a related good news, Angular now ships partially compiled packages!
Since Angular v12, it was possible to ship libraries in the “partially compiled” format,
making them directly consumable by Ivy projects, without the need to run ngcc
on them.
Angular itself was, weirdly enough, still shipping View Engine packages,
making ngcc
a required step to compile Angular itself in Ivy format,
and slowing down the first build.
This is no longer the case, and the packages are now shipped in the “partially compiled” format,
making ngcc
no longer required, and the first build much faster 🚀.
When the rest of the ecosystem is ready, we’ll say goodbye to ngcc
.
Our own tiny libraries, ngx-valdemort for handling form error messages,
and ngx-speculoos for simplifying unit-testing,
were already shipped in the “partially compiled” format of course 😎.
Forms
In a near future, we should finally have strictly typed forms
(see the Angular v14 section below).
In the meantime, a small improvement landed:
status
and statusChanges
are now strictly typed as FormControlStatus
and Observable<FormControlStatus>
instead of string
and Observable<any>
previously.
FormControlStatus
is a new union type of the various status values:
'VALID' | 'INVALID' | 'PENDING' | 'DISABLED'
.
This is technically a breaking change,
but unless you were doing weird things,
that should work fine.
Templates
The fullTemplateTypeCheck
compiler option is now deprecated
in favor of the strictTemplates
option.
strictTemplates
is technically more strict,
as it has more checks, but you should definitely switch to it.
The longhand binding prefixes in the template syntax are also deprecated.
So if you ever used bind-input
or on-click
in your templates,
you should now use the shorthand (and way more common) [input]
and (click)
syntax.
Did you even know that was a thing? 😉
Pipes
The date
pipe has an optional second argument if you want to specify the timezone or timezone offset:
{{ date | date: "shortTime":"+1200" }}
Angular v13 added the possibility to define the default timezone or timezone offset to use
for the date
pipe, instead of having to repeat it in every template.
To do so, you’ll have to use the special token DATE_PIPE_DEFAULT_TIMEZONE
:
providers: [
{ provide: DATE_PIPE_DEFAULT_TIMEZONE, useValue: '+1200' }
]
Core with factory-less APIs
The createComponent
API has been simplified to accept
a component class directly instead of a component factory.
Until now, you had to use this pretty terrible API
to create a new component instance dynamically:
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
ngAfterViewInit() {
const greetingsFactory =
this.componentFactoryResolver.resolveComponentFactory(GreetingsComponent);
this.greetings.createComponent(greetingsFactory);
}
Ivy made this change possible, and you can now write:
ngAfterViewInit() {
this.greetings.createComponent(GreetingsComponent);
}
No more factories \o/!
Tests
The new teardown
behavior of the TestBed
is now enabled by default.
This can seriously speed up your tests!
It has been introduced in Angular v12.1,
and you can read more about it in our blog post.
As it is now the default, you can remove the opt-in flag from your TestBed
configuration.
Note that an automatic migration will opt-out of this behavior
if you did not opt-in previously,
to avoid potential issues
(if your tests were relying on the broken teardown behavior).
I suggest you remove the teardown
flag from your TestBed
configuration
if the migration adds it,
and migrate your tests to the new behavior,
as this can lead to 3 times faster ng test
.
Router
routerLink
has a breaking change:
until now, giving it null
or undefined
has the same behavior as giving it []
(and navigated to the same page),
and there was no way to disable the link navigation.
In v13, if you give null
or undefined
to routerLink
,
then the navigation is disabled (and the href
attribute is removed from the link).
This is a cool new feature,
and to avoid breaking your code,
a migration will automatically update [routerLink]=""
to [routerLink]="[]"
as this was probably the intended goal.
routerLinkActive
now has a new output isActiveChange
that emits true
when the link becomes active, and false
when it becomes inactive.
This is handy if you want to apply a style somewhere else than on the link itself: <a routerLink="/me" routerLinkActive="active-link" (isActiveChange)="doSomething($event)">
.
routerOutlet
also gained two outputs: attach
and detach
to let you know when an instance is detached or re-attached when using a RouteReuseStrategy
(which is different than the activate
and deactivate
outputs that already existed,
and emits when a component is instantiated or destroyed by the outlet).
A new option called canceledNavigationResolution
has been added to the Router
to correctly restore the browser history in the case a navigation was canceled by CanDeactivate
guard.
If you encountered this issue,
you can now add router.canceledNavigationResolution = 'computed';
to your application.
This may become the default behavior in the future.
Service worker
The activateUpdate
and checkForUpdate
promises now return true
if the update was activated and false
if no update was available
instead of void
until now.
As a result, developers no longer have to check the activated
observable to know if the call resulted in an update or not.
activated
is now unnecessary and deprecated.
The available
observable is also deprecated,
and replaced by versionUpdates
which provides the same information,
and even more, as it also emits if a new version is available on the server (not yet downloaded) and if an installation of a new version failed.
Angular v14
What to expect in v14? As the team is now more openly sharing its goals, I can freely talk about the next version (without breaking the NDA I signed as an Angular team member 😅).
Some RFCs have been released and are being discussed by the community.
The most awaited one is probably the one about
standalone components (or how to make modules optionals).
The idea is to introduce a new flag in the @Component
decorators
(and @Directive
/@Pipe
decorators)
to mark them as standalone.
By doing so, a component can then be used without the need to be declared in a module.
It can directly declare what it uses.
This opens a ton of possibilities,
like getting rid of modules in most cases (they would still be useful for a few things),
API simplifications, components lazy-loading, etc 😍.
Another cool discussion started around faster developer experience with type-checking in the background.
The gist of the idea would be to have ng serve
running type-checking in the background,
hence making sure that the TypeScript compilation is not slowing down the feedback loop.
In most cases, everything is fine with our code,
and we just want to see the result in the browser as fast as possible.
We would still have compilation errors if something is broken, just a bit later.
One idea would be to leverage the awesome Vite tooling,
which does that, and much more.
Vite is the new “hot” tool in the JS world, with Vue, Svelte, and React developers already using it.
Without digging too much into the details,
one of the strengths of Vite is to leverage ESM modules
to give a much faster reloading experience while developing.
In this context, the recent packaging changes in the Angular world
that switches the shipped libraries to ESM modules make a lot of sense.
If that ever becomes a reality,
it would bring a massive improvement in the developer experience ✨.
One last really exciting feature is the experimental PR about typed forms. This is a feature requested by developers a long long time ago, and we may see a typed version of the Reactive Forms API in the future (maybe v14?). The PR is an experiment and will not be merged without a more formal RFC, but it gives an idea of what it would look like. Without too many breaking changes, and a lot of TypeScript devilries, most APIs would be the same, but type-safe.
Even something like form.get('user.address.street').value
would be properly typed 😲!
Stay tuned!
All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!