DEV Community

Cover image for What's new in Angular 18
Gergely Szerovay for This is Angular

Posted on • Originally published at angularaddicts.com

What's new in Angular 18

Since I published my 

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(),
   ]
 });
Enter fullscreen mode Exit fullscreen mode

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 FormControlFormGroup, 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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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}
Enter fullscreen mode Exit fullscreen mode

📌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 {}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

📌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 `/`;
      }
    }
  },
  // ...,
];
Enter fullscreen mode Exit fullscreen mode

📌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 and Map.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)

Collapse
 
jangelodev profile image
João Angelo

Hi Gergely Szerovay,
Top, very nice !
Thanks for sharing

Collapse
 
varshav profile image
Varsha VM • Edited

Thanks for sharing
Httpclientmodule deprecation was confusing.
Added provideHttpClient(withInterceptorsFromDi(), withFetch()) inside providers in app.config.ts but now my error is gone.