What's new in Angular 19.2?
Angular 19.2.0 is here!
This is a minor release with some nice features: let’s dive in!
Angular the documentary
This is not really linked to Angular v19.2, but it’s worth mentioning that the Honeypot channel released a documentary retracing the history of Angular, with interviews of the Angular team members (old and new):
TypeScript 5.8 support
Angular v19.2 now supports TypeScript 5.8, which is still in RC but should be out soon. This means you’ll be able to use the latest version of TypeScript in your Angular applications. You can check out the TypeScript 5.8 release notes to learn more about the new features.
resource() and rxResource() changes
Some changes happened in the recently introduced resource
and rxResource
APIs.
resource
was introduced in Angular 19.0
as an experimental API to handle asynchronous resources in Angular applications:
list(): ResourceRef<Array<UserModel> | undefined> {
return resource({
loader: async () => {
const response = await fetch('/users');
return (await response.json()) as Array<UserModel>;
}
});
}
Angular v19.2 adds the possibility to define a defaultValue
option that will be used as the initial value of the resource
or when the resource is in error (instead of undefined
by default):
list(): ResourceRef<Array<UserModel>> {
return resource({
// 👇 used when idle, loading, or in error
defaultValue: [],
loader: async () => {
const response = await fetch('/users');
return (await response.json()) as Array<UserModel>;
}
});
}
Angular v19.2 also added the possibility to create resources with streamed response data.
A streaming resource is defined with a stream option instead of a loader option.
This stream function returns a promise of a signal (yes, I needed to read it twice as well).
The signal value must be of type ResourceStreamItem
:
an object with a value or an error property.
When the promise is resolved, the loader can continue to update that signal over time,
and the resource will update its value and error every time the signal’s item changes.
You can build this stream yourself, using a WebSocket for example. We can also imagine that some libraries such as Firebase could provide a stream function that would be directly usable:
list(): ResourceRef<Array<UserModel> | undefined> {
return resource({
// firebaseCollection does not exist in real-life
stream: async ({ abortSignal }) => await firebaseCollection('users', abortSignal)
});
}
This stream feature had been leveraged by the rxResource
API,
and you can now have a stream of values by returning an observable that emits several times.
The resource will be updated every time a new value is emitted,
whereas only the first value was emitted when introduced in Angular v19.
readonly sortOrder = signal<'asc' | 'desc'>('asc');
readonly usersResource = rxResource({
request: () => ({ sort: this.sortOrder() }),
// 👇 stream that fetches the value now and every 10s
loader: ({ request }) =>
timer(0, 10000).pipe(
switchMap(() => this.httpClient.get<Array<UserModel>>('/users', { params: { sort: request.sort } }))
)
});
New httpResource() API!
The main feature of this release is the introduction of the httpResource
API.
This API allows you to easily create resources that fetch data from an HTTP endpoint.
We wrote a dedicated blog post to explain how to use it:
👉 A guide to HTTP calls with httpResource()
The official RFCs for Resource Architecture and Resource APIS are also out if you’re curious.
Template strings in templates
The Angular compiler now supports template strings in templates:
<p>{{ `Hello, ${name()}!` }}</p>
<button [class]="`btn-${theme()}`">Toggle</button>
Here name
and theme
are signals that contain strings.
You can even use pipes in the dynamic part of the template string:
<p>{{ `Hello, ${name() | uppercase}!` }}</p>
git This is a nice addition and I hope we’ll see arrow functions in templates soon!
Migration to self-closing tags
A migration has been added to convert void elements to self-closing tags.
This is just a cosmetic change, and some of you may have already done it via angular-eslint
and its prefer-self-closing-tags
rule.
If that’s not the case for you, you can run:
ng generate @angular/core:self-closing-tag
Forms validators
The Validators.required
, Validators.minLength
, and Validators.maxLength
validators
now work with Set
in addition to Array
and string
:
const atLeastTwoElementsValidator = Validators.minLength(2);
// minLength error before v19.2
atLeastTwoElementsValidator(new FormControl("a")); // string
atLeastTwoElementsValidator(new FormControl(["a"])); // Array
// 👇 NEW in v19.2! minLength error as well with a Set
atLeastTwoElementsValidator(new FormControl(new Set(["a"]))); // Set
Animation package
The @angular/animations
package is slowly being retired:
there has been no major update since its author left the Angular team a few years ago,
and it is not actively maintained anymore.
The team has removed dependencies on it in most packages (and in Angular Material as well),
which means that you now safely remove it from your project if you don’t use it directly.
To reflect that, the project skeleton generated by the CLI does not include it anymore in v19.2.
Angular CLI
AoT support for Karma, Jest, and WTR
It is now possible to run your tests with AOT compilation with Karma, Jest, and Web Test Runner, instead of the default JIT compilation that has been used so far. This is great as it can catch issues in your test components (missing required inputs, etc).
Sadly, some test features are not available with AOT compilation in tests.
For example, TestBed.overrideComponent
, TestBed.overrideTemplate
, etc are not supported
as they rely on JIT compilation.
I really hope that we’ll soon have new TestBed
APIs that work with AOT compilation!
In the meantime, you can give it a try by adding the aot: true
option in your angular.json
configuration file.
Karma builder
The Karma application builder (introduced in v19)
has been moved to the @angular/build
package.
This means you can now only use this dependency
and get rid of the @angular-devkit/build-angular
one.
SSR
provideServerRoutesConfig
has been deprecated and renamed provideServerRouting
,
and its appShellRoute
option has been replaced with a withAppShell
option,
to make the API similar to the other in Angular.
Before:
provideServerRoutesConfig(serverRoutes, { appShellRoute: "" });
After:
provideServerRouting(serverRoutes, withAppShell(AppComponent));
A note-worthy new feature: routes defined with a matcher
are now supported by Angular SSR,
allowing us to define their render mode.
Note that it can only be Server
or Client
for these routes but not Prerender
.
Summary
That’s all for this release. The next one should be v20, and we hope to see some news on the “forms with signals” 🤞 Stay tuned!
All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!