Skip to content

Upgrading @angular/router 17 to 18

Breaking17.3.12 โ†’ 18.2.14Breaking35Security1Platform1Deprecated10New41Changed5Fixed222Other6

BreakingUpgrade verdict

30 breaking changes and a platform requirement change and a security fix.

  • Server-side apps now receive a context object when bootstrapping instead of using a shared global platform.
  • Tests using fakeAsync will now run any pending timers when the test function finishes, unless you turn this off.
  • A long-deprecated animation method is gone, so any code still calling it will break.
  • Two deprecated platform-check functions are removed, so code using them must be updated.
Top 5 of 42 that need code or config changes

Node.js requirement changed in 18.1.0-next.1: ^18.13.0 || >=20.9.0 โ†’ ^18.19.1 || ^20.11.1 || >=22.0.0.

Breaking30
Introduces BootstrapContext for server bootstrapping, removing reliance on a global platform injector.
BootstrapContextbootstrapApplicationgetPlatform()destroyPlatform()
fakeAsync now flushes pending timers at the end of the given function by default; use {flush: false} to opt out.
fakeAsync
Removes deprecated matchesElement from AnimationDriver.
AnimationDrivermatchesElement
Removes deprecated isPlatformWorkerApp and isPlatformWorkerUi APIs.
isPlatformWorkerAppisPlatformWorkerUi
Removes support for unassignable expressions in two-way bindings.
Removes deprecated transfer state APIs.
StateKeyTransferStatemakeStateKey
Removes deprecated Testability methods.
Testability
Removes the unused RESOURCE_CACHE_PROVIDER API from platform-browser-dynamic.
RESOURCE_CACHE_PROVIDER
Removes the deprecated platformDynamicServer API from platform-server.
platformDynamicServer
Removes the deprecated ServerTransferStateModule API from platform-server.
ServerTransferStateModule
Removes deprecated useAbsoluteUrl and baseUrl from PlatformConfig.
PlatformConfiguseAbsoluteUrlbaseUrl
Removes legacy URL handling logic from platform-server.
Angular no longer supports TypeScript versions older than 5.4.
ComponentFixture autoDetect no longer refreshes OnPush host views that are not dirty.
ComponentFixtureautoDetectOnPushmarkForCheckChangeDetectionStrategy.Default
Excludes authenticated HTTP requests from transfer caching by default; opt out with includeRequestsWithAuthHeaders.
withHttpTransferCacheincludeRequestsWithAuthHeaders
Removes deprecated Testability methods increasePendingRequestCount, decreasePendingRequestCount and getPendingRequestCount.
increasePendingRequestCountdecreasePendingRequestCountgetPendingRequestCount
Angular only supports writable expressions inside two-way bindings.
OnPush root views must be marked dirty for host bindings to refresh.
OnPush
Guards can now return RedirectCommand for redirects in addition to UrlTree, so code expecting only boolean or UrlTree in Route types must be adjusted.
RedirectCommandUrlTreeRoute
Allows Route.redirectTo to be a function in addition to a string, so code expecting only a string must be adjusted.
Route.redirectToRoute
Guard redirects via UrlTree now use replaceUrl when the initial navigation used replaceUrl; use RedirectCommand to customize options.
UrlTreereplaceUrlNavigationBehaviorOptionsRedirectCommand
Providers for routed components now always come from the route injector hierarchy and never inherit from the RouterOutlet.
RouterOutletNgModuleproviders
Completes the removal of the deprecated async function; use waitForAsync instead.
asyncwaitForAsync
ComponentFixture.whenStable now matches ApplicationRef.isStable, including unfinished router navigations and HttpClient requests.
ComponentFixture.whenStableApplicationRef.isStableHttpClientHttpTestingController.verify()
ComponentFixture.isStable now always switches to true asynchronously instead of synchronously in some scenarios.
ComponentFixture.isStable
Change detection keeps refreshing views attached to ApplicationRef that remain marked for check, which can surface NG0103 infinite loops.
ApplicationRefChangeDetectorRef.detectChangesNG0103
Change detection timing with event or run coalescing in NgZone is now the first of setTimeout or requestAnimationFrame.
NgZonesetTimeoutrequestAnimationFrameafterNextRender
Newly created views marked for check and reattached during change detection are now guaranteed to refresh in that same cycle.
ExpressionChangedAfterItHasBeenCheckedError
Angular now runs change detection even when state updates originate outside the zone, which may add change detection rounds in tests.
provideZoneChangeDetection()NgZoneSchedulingMode.NgZoneOnlybootstrapApplication()bootstrapModule()BootstrapOptions
ComponentFixture.autoDetect now runs change detection within ApplicationRef.tick, changing refresh order in tests.
ComponentFixture.autoDetectApplicationRef.tick
Security1
Addresses Trusted Types violations in @angular/upgrade.
@angular/upgrade
Platform1
Drops support for TypeScript versions older than 5.4.
Deprecated10
Deprecates the ignoreChangesOutsideZone option.
ignoreChangesOutsideZone
Adds back the phase flag option as a deprecated API.
Deprecates Local Data API functions.
Deprecates @Component.interpolation.
@Component.interpolation
Deprecates HttpClientModule and related modules.
HttpClientModule
Deprecates getCurrencySymbol and related locale currency, date, number, and plural formatting functions.
getCurrencySymbolgetLocaleCurrencyCodegetLocaleCurrencyNamegetLocaleCurrencySymbolgetLocaleDateFormatgetLocaleDateTimeFormatgetLocaleDayNamesgetLocaleDayPeriods
Deprecates @Component.interpolation in favor of Angular's delimiters.
@Component.interpolation
Deprecates HttpClientModule, HttpClientXsrfModule and HttpClientJsonpModule, which can be replaced by provider functions only.
HttpClientModuleHttpClientXsrfModuleHttpClientJsonpModule
Deprecates @Component.interpolation in favor of Angular's delimiters.
@Component.interpolation
Deprecates HttpClientModule and related modules in favor of provider functions.
HttpClientModuleHttpClientXsrfModuleHttpClientJsonpModule

Generated by DepDelta from published .d.ts files. Not mixed with prose notes.

  • removed: property OutletContext.injector: EnvironmentInjector | null
  • changed: function mapToCanActivate(providers: Array<Type<{ canActivate: CanActivateFn }>>): CanActivateFn[] โ†’ function mapToCanActivate(providers: Array<Type<CanActivate>>): CanActivateFn[]
  • changed: function mapToCanActivateChild(providers: Array<Type<{ canActivateChild: CanActivateChildFn }>>): CanActivateChildFn[] โ†’ function mapToCanActivateChild(providers: Array<Type<CanActivateChild>>): CanActivateChildFn[]
  • changed: function mapToCanDeactivate<T = unknown>(providers: Array<Type<{ canDeactivate: CanDeactivateFn<T> }>>): CanDeactivateFn<T>[] โ†’ function mapToCanDeactivate<T = unknown>(providers: Array<Type<CanDeactivate<T>>>): CanDeactivateFn<T>[]
  • changed: function mapToCanMatch(providers: Array<Type<{ canMatch: CanMatchFn }>>): CanMatchFn[] โ†’ function mapToCanMatch(providers: Array<Type<CanMatch>>): CanMatchFn[]
  • changed: function mapToResolve<T>(provider: Type<{ resolve: ResolveFn<T> }>): ResolveFn<T> โ†’ function mapToResolve<T>(provider: Type<Resolve<T>>): ResolveFn<T>
  • changed: function withNavigationErrorHandler(fn: (error: NavigationError) => void): NavigationErrorHandlerFeature โ†’ function withNavigationErrorHandler(handler: (error: NavigationError) => unknown | RedirectCommand): NavigationErrorHandlerFeature
  • changed: method RouterLink.ngOnChanges(changes: SimpleChanges): void โ†’ method RouterLink.ngOnChanges(changes?: SimpleChanges): void
  • changed: method RouterLinkWithHref.ngOnChanges(changes: SimpleChanges): void โ†’ method RouterLinkWithHref.ngOnChanges(changes?: SimpleChanges): void
  • changed: method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, environmentInjector?: EnvironmentInjector | null): void โ†’ method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector): void
  • changed: method RouterOutletContract.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector | null): void โ†’ method RouterOutletContract.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector): void
  • changed: property Route.redirectTo?: string โ†’ property Route.redirectTo?: string | RedirectFunction
  • changed: set RouterLink.routerLink(commands: any[] | string | null | undefined) โ†’ set RouterLink.routerLink(commandsOrUrlTree: any[] | string | UrlTree | null | undefined)
  • changed: set RouterLinkWithHref.routerLink(commands: any[] | string | null | undefined) โ†’ set RouterLinkWithHref.routerLink(commandsOrUrlTree: any[] | string | UrlTree | null | undefined)
  • changed: type GuardResult = boolean | UrlTree โ†’ type GuardResult = boolean | UrlTree | RedirectCommand
  • changed: type QueryParamsHandling = 'merge' | 'preserve' | '' โ†’ type QueryParamsHandling = 'merge' | 'preserve' | 'replace' | ''
  • changed: type ResolveFn<T> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => MaybeAsync<T> โ†’ type ResolveFn<T> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => MaybeAsync<T | RedirectCommand>
  • added: class RedirectCommand
  • added: constructor ChildrenOutletContexts(rootInjector: EnvironmentInjector)
  • added: constructor OutletContext(rootInjector: EnvironmentInjector)
  • added: constructor RedirectCommand(redirectTo: UrlTree, navigationBehaviorOptions?: NavigationBehaviorOptions | undefined)
  • added: get OutletContext.injector(): EnvironmentInjector
  • added: property RouterConfigOptions.defaultQueryParamsHandling?: QueryParamsHandling
  • added: readonly property NavigationBehaviorOptions.browserUrl?: UrlTree | string
  • added: readonly property RedirectCommand.navigationBehaviorOptions?: NavigationBehaviorOptions | undefined
  • added: readonly property RedirectCommand.redirectTo: UrlTree
  • added: set OutletContext.injector(_: EnvironmentInjector)
  • added: type RedirectFunction = (redirectData: Pick<ActivatedRouteSnapshot, 'routeConfig' | 'url' | 'params' | 'queryParams' | 'fragment' | 'data' | 'outlet' | 'title'>) => string | UrlTree