Since I published my
- Master Angular 17 Study guide ,
- Master Angular 17.1 and 17.2 Study guide and the
- What's new in Angular 17.3 article
the Angular team released a new major version: Angular 18.
🎯Changes and new features
In this article, I list out the most important changes and new features, also share resources that will teach you how these new Angular features work:
- Control flow syntax and defer blocks are now stable
- Angular Material 3 is now stable, material.angular.io is updated by the new themes and documentation
- Experimental change detection without ZoneJS:
provideZonelessChangeDetection
- Unified control state change events
- Fallback content for
ng-content
- Route redirect functions
- Coalescing is enabled by default
-
HttpClientModule
deprecation - Typescript 5.4 support
Now angular.dev is the official website for the Angular documentation.
📌Experimental change detection without ZoneJS: provideZonelessChangeDetection
Official docs: Angular without ZoneJS (Zoneless)
Merge request / commit: feat(core): Add zoneless change detection provider as experimental
Angular 18 introduces a new, zoneless way to trigger change detection. When using provideExperimentalZonelessChangeDetection
, Angular will use use Angular APIs to schedule change detection, including:
ChangeDetectorRef.markForCheck
ComponentRef.setInput
- Updating a signal that is read in a template
- When bound host or template listeners are triggered
- When attaching a view that was marked dirty by one of the above
- When removing a view
- When registering a render hook (templates are only refreshed if render hooks do one of the above)
You can try the zoneless change detection with the new provideExperimentalZonelessChangeDetection
provider, and components using OnPush
change detection strategy:
bootstrapApplication(App, {
providers: [
provideExperimentalZonelessChangeDetection(),
]
});
Angular CDK and Angular Material also introduced has zoneless support.
📌Unified control state change events
Official docs: AbstractControl.events
Merge request / commit: feat(forms): Unified Control State Change Events
In Angular 18, the AbstractControl
class (the base class for FormControl
, FormGroup
, and FormArray
) introduced a new events: Observable<ControlEvent<TValue>>
property. This property is an observable, that emits for value, status, pristine or touched changes.
@Component({
selector: 'app-abstract-control-events',
standalone: true,
imports: [ReactiveFormsModule],
template: ` <input [formControl]="titleInputControl" /> `,
})
export class AbstractControlEventsComponent {
titleInputControl = new FormControl<string | null>('', Validators.required);
constructor() {
this.titleInputControl.events.pipe(takeUntilDestroyed()).subscribe(console.log);
}
}
If you click on the input field in the example, enter a character, then click outside of the input field, the following events are logged on the browser's console:
PristineChangeEvent {pristine: false, source: FormControl2}
ValueChangeEvent {value: 'a', source: FormControl2}
StatusChangeEvent {status: 'VALID', source: FormControl2}
TouchedChangeEvent {touched: true, source: FormControl2}
📌Fallback content for ng-content
Official docs: Content projection with ng-content
Merge request / commit: feat(core): add support for fallback content in ng-content
In Angular 18, we can specify a fallback content for <ng-content>
, this content is rendered when there is no content specified for projection in the parent component:
@Component({
selector: 'app-header',
template: `
<ng-content select=".title">Default tilte</ng-content>
<ng-content select=".explanation">There is no explanation for this title</ng-content>
`,
})
export class HeaderComponent {}
@Component({
selector: 'app-wrapper',
template: `
<app-header>
<span class="title">First chapter</span>
</app-header>
`,
})
export class WrapperComponent {}
These components are rendered as:
<app-wrapper>
<app-header>
<span class="title">First chapter</span>
There is no explanation for this title
</app-header>
</app-wrapper>
📌Route redirect functions
Official docs: Common router tasks: Setting up redirects
Merge request / commit: feat(router): Allow Route.redirectTo to be a function which returns a string or UrlTree
In Angular 18, a route's redirectTo
property can be a function that returns a string or UrlTree
, enabling us to create more dynamic redirects based on the application's state:
export const routes: Routes = [
// ...,
{
path: "prods", //legacy path
redirectTo: ({ queryParams }) => {
const productId = queryParams['id'];
if (productId) {
return `/products/${productId}`;
} else {
return `/`;
}
}
},
// ...,
];
📌Coalescing is enabled by default
Official docs: NgZoneOptions
Starting from Angular 18, zone coalescing is enabled by default (eventCoalescing: true
) for newly created applications. Zone coalescing can reduce the number of the change detection cycles and improve the app's performance.
📌HttpClientModule
deprecation
Merge request / commit: refactor(http): Deprecate HttpClientModule & related modules,Migration schematics for HttpClientModule
Starting with v18, the preferred way of providing the HTTP client are provideHttpClient()
and provideHttpClientTesting()
. HttpClientModule
and HttpClientTestingModule
are deprecated now.
When you run ng update @angular/core
, Angular can automatically migrate your code to use the preferred provideHttpClient()
and provideHttpClientTesting()
functions instead of the deprecated modules.
📌Typescript 5.4 support
Merge request / commit: feat(compiler-cli): drop support for TypeScript older than 5.4
Daniel Rosenwasser highlighted the most interesting new features of Typescript 5.4 in his announcement:
- Preserved Narrowing in Closures Following Last Assignments
- The
NoInfer
Utility Type -
Object.groupBy
andMap.groupBy
- Support for
require()
calls in--moduleResolution bundler
and--module preserve
- Checked Import Attributes and Assertions
- Quick Fix for Adding Missing Parameters
- Auto-Import Support for Subpath Imports
👨💻About the author
My name is Gergely Szerovay, I worked as a data scientist and full-stack developer for many years, and I have been working as frontend tech lead, focusing on Angular-based frontend development. As part of my role, I'm constantly following how Angular and the frontend development scene in general is evolving.
Angular has advancing very rapidly over the past few years, and in the past year, with the rise of generative AI, our software development workflows have also evolved rapidly. In order to closely follow the evolution of AI-assisted software development, I decided to start building AI tools in public, and publish my progress on AIBoosted.dev , Subscribe here 🚀
Follow me on Substack (Angular Addicts), Substack (AIBoosted.dev), Medium, Dev.to, X or LinkedIn to learn more about Angular, and how to build AI apps with AI, Typescript, React and Angular!
Top comments (2)
Hi Gergely Szerovay,
Top, very nice !
Thanks for sharing
Thanks for sharing
Httpclientmodule deprecation was confusing.
Added provideHttpClient(withInterceptorsFromDi(), withFetch()) inside providers in app.config.ts but now my error is gone.