Skip to content

Upgrading @angular/router 12 to 13

Breaking12.2.17 → 13.4.0Breaking17Security1Platform6Deprecated12New41Changed14Fixed142Other6

BreakingUpgrade verdict

14 breaking changes and 6 platform requirement changes and a security fix.

  • Tests that fake the browser location behave more like real browsers now, so some router tests may need updating.
  • Angular Elements no longer declares a wrong peer dependency.
  • Code or libraries that still import WrappedValue from Angular core will break and must remove that usage.
  • URLs with a question mark inside a query value are now parsed correctly rather than truncated.
Top 5 of 33 that need code or config changes

Node.js requirement changed in 13.0.0-next.13: ^12.14.1 || >=14.0.0 → ^12.20.0 || ^14.15.0 || >=16.10.0.

Breaking14
SpyLocation used by RouterTestingModule no longer emits popstate on Location.go, and simulateHashChange now triggers both hashchange and popstate.
SpyLocationRouterTestingModuleLocation.gosimulateHashChangeRouter
Removes the incorrect @angular/platform-browser peer dependency from @angular/elements.
@angular/platform-browser
WrappedValue can no longer be imported from @angular/core, which may cause compile or runtime failures in outdated libraries.
WrappedValue@angular/core
The default url serializer now correctly keeps question marks inside query parameter values instead of dropping everything after them.
routerLink no longer treats null and undefined as empty string, and href is now an attribute binding returning the full native URL.
routerLinkHostBindingDebugElement.propertiesRouterLink
The router no longer replaces the browser URL when a new navigation cancels an ongoing one.
navigationIdNavigationCancellocation.replaceStateurlChangesSpyLocation
Route.loadChildren no longer accepts a string, and NgModuleFactoryLoader, SystemJsNgModuleFactoryLoader, SpyNgModuleFactoryLoader and DeprecatedLoadChildren are removed.
Route.loadChildrenNgModuleFactoryLoaderSystemJsNgModuleFactoryLoaderSpyNgModuleFactoryLoaderDeprecatedLoadChildrensetupTestingRouter
Removes support for the deprecated WrappedValue.
WrappedValue
Removes the ng-add schematic from @angular/elements.
ng-add
Removes support for the loadChildren string syntax.
loadChildren
Removes the ng-add schematic from @angular/elements.
ng-add
Hardens attribute and property binding rules for <iframe> elements, which may require updates to existing iframe usages.
<iframe>
SwUpdate#activateUpdate and SwUpdate#checkForUpdate now return Promise<boolean>, which may cause TypeScript type-checking failures.
SwUpdate#activateUpdateSwUpdate#checkForUpdatePromise<boolean>
AbstractControl.status is narrowed to FormControlStatus and statusChanges to Observable<FormControlStatus>, which may break comparisons against invalid strings.
FormControlStatusAbstractControl.statusstatusChanges
Security1
Hardens attribute and property binding rules for <iframe> elements.
<iframe>
Platform6
Adds support for TypeScript 4.5.
TypeScript versions older than 4.4.2 are no longer supported.
NodeJS versions older than v12.20.0 are no longer supported due to NodeJS package exports with subpath patterns.
Drops support for TypeScript 4.2 and 4.3.
Adds support for TypeScript 4.4.
Updates the supported Node.js version range to include v16.
Deprecated12
Deprecates the CachedResourceLoader and RESOURCE_CACHE_PROVIDER symbols, which are no longer needed since Ivy.
CachedResourceLoaderRESOURCE_CACHE_PROVIDER
Deprecates the ComponentFactory and ComponentFactoryResolver classes since Ivy makes factory resolution unnecessary.
ComponentFactoryComponentFactoryResolver
Deprecates the unused CompilerOptions.useJit and CompilerOptions.missingTranslation config options, which have no effect since Ivy.
CompilerOptions.useJitCompilerOptions.missingTranslation
Deprecates the tap operator subscribe signature with separate callback arguments in favor of an observer argument.
tap
Deprecates factory-based downgradeModule calls in favor of NgModule class based calls.
downgradeModule
TestRequest no longer accepts ErrorEvent for simulated XHR errors; pass ProgressEvent instead.
TestRequestErrorEventProgressEvent
renderModuleFactory in @angular/platform-server is deprecated; use renderModule instead.
renderModuleFactoryrenderModule@angular/platform-server
The SwUpdate#activated observable is deprecated because the return value of SwUpdate#activateUpdate() now indicates the outcome.
SwUpdate#activatedSwUpdate#activateUpdate()
The SwUpdate#availalbe observable is deprecated in favor of SwUpdate#versionUpdates and VersionReadyEvent.
SwUpdate#availalbeSwUpdate#versionUpdatesVersionReadyEvent
Deprecates the ViewEngine-based renderModuleFactory.
renderModuleFactory
Deprecates the SwUpdate#activated observable.
SwUpdate#activatedSwUpdate#activateUpdate()
Deprecates the SwUpdate#availalbe observable in favor of SwUpdate#versionUpdates.
SwUpdate#availalbeSwUpdate#versionUpdatesVersionReadyEvent

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

  • removed: class ɵangular_packages_router_router_h implements OnDestroy
  • removed: class ɵangular_packages_router_router_l
  • removed: class ɵangular_packages_router_router_m<T>
  • removed: class ɵangular_packages_router_router_n<T>
  • removed: class ɵangular_packages_router_router_o implements OnDestroy
  • removed: const ɵangular_packages_router_router_a: InjectionToken<void>
  • removed: constructor ɵangular_packages_router_router_h(injector: Injector)
  • removed: constructor ɵangular_packages_router_router_m(root: ɵangular_packages_router_router_n<T>)
  • removed: constructor ɵangular_packages_router_router_n(value: T, children: ɵangular_packages_router_router_n<T>[])
  • removed: constructor ɵangular_packages_router_router_o(router: Router, viewportScroller: ViewportScroller, options?: { scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'; anchorScrolling?: 'disabled' | 'enabled' })
  • removed: function ɵangular_packages_router_router_b(): NgProbeToken
  • removed: function ɵangular_packages_router_router_c(router: Router, viewportScroller: ViewportScroller, config: ExtraOptions): ɵangular_packages_router_router_o
  • removed: function ɵangular_packages_router_router_d(platformLocationStrategy: PlatformLocation, baseHref: string, options?: ExtraOptions): HashLocationStrategy | PathLocationStrategy
  • removed: function ɵangular_packages_router_router_e(router: Router): any
  • removed: function ɵangular_packages_router_router_f(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Route[][], opts?: ExtraOptions, urlHandlingStrategy?: UrlHandlingStrategy, routeReuseStrategy?: RouteReuseStrategy): Router
  • removed: function ɵangular_packages_router_router_g(router: Router): ActivatedRoute
  • removed: function ɵangular_packages_router_router_i(r: ɵangular_packages_router_router_h): () => Promise<any>
  • removed: function ɵangular_packages_router_router_j(r: ɵangular_packages_router_router_h): (bootstrappedComponentRef: ComponentRef<any>) => void
  • removed: function ɵangular_packages_router_router_k(): ReadonlyArray<Provider>
  • removed: get ɵangular_packages_router_router_m.root(): T
  • removed: method ɵangular_packages_router_router_h.appInitializer(): Promise<any>
  • removed: method ɵangular_packages_router_router_h.bootstrapListener(bootstrappedComponentRef: ComponentRef<any>): void
  • removed: method ɵangular_packages_router_router_h.ngOnDestroy(): void
  • removed: method ɵangular_packages_router_router_n.toString(): string
  • removed: method ɵangular_packages_router_router_o.init(): void
  • removed: method ɵangular_packages_router_router_o.ngOnDestroy(): void
  • removed: property ɵangular_packages_router_router_n.children: ɵangular_packages_router_router_n<T>[]
  • removed: property ɵangular_packages_router_router_n.value: T
  • removed: readonly property ɵangular_packages_router_router_o.viewportScroller: ViewportScroller
  • removed: type DeprecatedLoadChildren = string
  • changed: class RouterState extends ɵangular_packages_router_router_m<ActivatedRoute> → class RouterState extends Tree<ActivatedRoute>
  • changed: class RouterStateSnapshot extends ɵangular_packages_router_router_m<ActivatedRouteSnapshot> → class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot>
  • changed: constructor Router(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location_2, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes) → constructor Router(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location_2, injector: Injector, compiler: Compiler, config: Routes)
  • changed: constructor RouterLink(router: Router, route: ActivatedRoute, tabIndex: string, renderer: Renderer2, el: ElementRef) → constructor RouterLink(router: Router, route: ActivatedRoute, tabIndexAttribute: string | null | undefined, renderer: Renderer2, el: ElementRef)
  • changed: constructor RouterPreloader(router: Router, moduleLoader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, preloadingStrategy: PreloadingStrategy) → constructor RouterPreloader(router: Router, compiler: Compiler, injector: Injector, preloadingStrategy: PreloadingStrategy)
  • changed: get RouterLink.urlTree(): UrlTree → get RouterLink.urlTree(): UrlTree | null
  • changed: get RouterLinkWithHref.urlTree(): UrlTree → get RouterLinkWithHref.urlTree(): UrlTree | null
  • changed: property RouterLinkWithHref.href: string → property RouterLinkWithHref.href: string | null
  • changed: type Data = { [name: string]: any } → type Data = { [key: string | symbol]: any }
  • changed: type LoadChildren = LoadChildrenCallback | DeprecatedLoadChildren → type LoadChildren = LoadChildrenCallback
  • changed: type ResolveData = { [name: string]: any } → type ResolveData = { [key: string | symbol]: any }
  • added: property ExtraOptions.canceledNavigationResolution?: 'replace' | 'computed'
  • added: property Router.canceledNavigationResolution: 'replace' | 'computed'
  • added: property RouterOutlet.attachEvents: EventEmitter<unknown>
  • added: property RouterOutlet.detachEvents: EventEmitter<unknown>
  • added: property RouterOutletContract.attachEvents?: EventEmitter<unknown>
  • added: property RouterOutletContract.detachEvents?: EventEmitter<unknown>
  • added: readonly property RouterLinkActive.isActiveChange: EventEmitter<boolean>
  • added: static property Router.ɵfac: i0.ɵɵFactoryDeclaration<Router, never>
  • added: static property Router.ɵprov: i0.ɵɵInjectableDeclaration<Router>
  • added: static property RouterLink.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, ':not(a):not(area)[routerLink]', never, { 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'state': 'state'; 'relativeTo': 'relativeTo'; 'routerLink': 'routerLink' }…
  • added: static property RouterLink.ɵfac: i0.ɵɵFactoryDeclaration<RouterLink, [null, null, { attribute: 'tabindex' }, null, null]>
  • added: static property RouterLinkActive.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, '[routerLinkActive]', ['routerLinkActive'], { 'routerLinkActiveOptions': 'routerLinkActiveOptions'; 'routerLinkActive': 'routerLinkActive' }, { 'isActiveChange': 'isActiveChange' }, ['links', 'linksWithHrefs']>
  • added: static property RouterLinkActive.ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkActive, [null, null, null, null, { optional: true }, { optional: true }]>
  • added: static property RouterLinkWithHref.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkWithHref, 'a[routerLink],area[routerLink]', never, { 'target': 'target'; 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'state': 'state'; 'relativeTo': 'rela…
  • added: static property RouterLinkWithHref.ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkWithHref, never>
  • added: static property RouterModule.ɵfac: i0.ɵɵFactoryDeclaration<RouterModule, [{ optional: true }, { optional: true }]>
  • added: static property RouterModule.ɵinj: i0.ɵɵInjectorDeclaration<RouterModule>
  • added: static property RouterModule.ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent], never, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent]>
  • added: static property RouterOutlet.ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, 'router-outlet', ['outlet'], {}, { 'activateEvents': 'activate'; 'deactivateEvents': 'deactivate'; 'attachEvents': 'attach'; 'detachEvents': 'detach' }, never>
  • added: static property RouterOutlet.ɵfac: i0.ɵɵFactoryDeclaration<RouterOutlet, [null, null, null, { attribute: 'name' }, null]>
  • added: static property RouterPreloader.ɵfac: i0.ɵɵFactoryDeclaration<RouterPreloader, never>
  • added: static property RouterPreloader.ɵprov: i0.ɵɵInjectableDeclaration<RouterPreloader>
  • added: static property ɵEmptyOutletComponent.ɵcmp: i0.ɵɵComponentDeclaration<ɵEmptyOutletComponent, 'ng-component', never, {}, {}, never, never>
  • added: static property ɵEmptyOutletComponent.ɵfac: i0.ɵɵFactoryDeclaration<ɵEmptyOutletComponent, never>
  • added: type ɵRestoredState = { [k: string]: any; navigationId: number; ɵrouterPageId?: number }
  • removed: export * from './testing/testing'
  • removed: class SpyNgModuleFactoryLoader implements NgModuleFactoryLoader
  • removed: constructor SpyNgModuleFactoryLoader(compiler: Compiler)
  • removed: function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], urlHandlingStrategy?: UrlHandlingStrategy): Router
  • removed: get SpyNgModuleFactoryLoader.stubbedModules(): { [path: string]: any }
  • removed: method SpyNgModuleFactoryLoader.load(path: string): Promise<NgModuleFactory<any>>
  • removed: set SpyNgModuleFactoryLoader.stubbedModules(modules: { [path: string]: any })
  • changed: function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], opts?: ExtraOptions, urlHandlingStrategy?: UrlHandlingStrategy): Router → function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, compiler: Compiler, injector: Injector, routes: Route[][], opts?: ExtraOptions | UrlHandlingStrategy, urlHandlingStrategy?: UrlHandlingStrategy, routeReuseStrategy?: RouteReuseStrategy): Router
  • added: static property RouterTestingModule.ɵfac: i0.ɵɵFactoryDeclaration<RouterTestingModule, never>
  • added: static property RouterTestingModule.ɵinj: i0.ɵɵInjectorDeclaration<RouterTestingModule>
  • added: static property RouterTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<RouterTestingModule, never, never, [typeof i1.RouterModule]>
  • removed: export * from './upgrade/upgrade'