Skip to content

Upgrading @angular/platform-browser 18 to 19

Breaking18.2.14 → 19.2.25Breaking101Security18Platform5New39Changed11Fixed228Other4

BreakingUpgrade verdict

93 breaking changes and 5 platform requirement changes and 18 security fixes.

  • If a translation adds an attribute Angular does not recognize, it will no longer appear in the rendered output.
  • On the server, apps must now pass a context object when starting up instead of relying on a shared global platform.
  • In templates, writing `this.` before a name now reads a component property instead of a template variable.
  • New components, directives and pipes no longer need to be declared in an NgModule unless you opt out.
Top 5 of 116 that need code or config changes
Breaking93
Angular now only applies known HTML attributes from translated ICU content; unknown attributes are dropped and not rendered.
Server bootstrapping no longer relies on a global platform injector; bootstrapApplication now takes a BootstrapContext.
BootstrapContextbootstrapApplicationgetPlatform()destroyPlatform()
this.foo property reads no longer refer to template context variables.
Angular directives, components and pipes are now standalone by default.
ExperimentalPendingTasks has been renamed to PendingTasks.
ExperimentalPendingTasksPendingTasks
createComponent now renders default fallback content with empty projectableNodes.
createComponentprojectableNodesng-content
The deprecated factories property in KeyValueDiffers has been removed.
KeyValueDiffersfactories
The name option in the ng add @localize schematic has been removed in favor of the project option.
nameproject
The deprecated BrowserModule.withServerTransition method has been removed.
BrowserModule.withServerTransitionAPP_ID
The Router.errorHandler property has been removed.
Router.errorHandlerwithNavigationErrorHandlerprovideRouterRouterModule.forRootresolveNavigationPromiseOnError
Disables standalone by default on older versions of Angular.
Flips the default value for standalone to true.
standalone
Treats directives, pipes and components as standalone by default.
Falls back to default ng-content when projectable nodes are empty.
ng-content
Elements switch to ComponentRef.setInput and remove custom scheduler.
ComponentRef.setInput
Removes the deprecated name option from localize.
name
Removes complete calls for migrated outputs.
Flips the default standalone flag in the route-lazy-loading migration.
Includes the output migration in the defaults of the signal migration.
Removes the deprecated BrowserModule.withServerTransition method.
BrowserModule.withServerTransition
Removes the setter for injector on OutletContext.
OutletContextinjector
Removes the deprecated BrowserModule.withServerTransition method.
BrowserModule.withServerTransitionAPP_ID
Renders default fallback content when projectableNodes is an empty array in createComponent.
createComponentprojectableNodesng-contentdocument.createTextNode
Fixes :host parsing in pseudo-selectors.
:host
Makes this.a always refer to class property a.
this.a
Timing changes for the effect API in developer preview.
effect
Does not migrate next calls in templates if not an EventEmitter.
EventEmitternext
Effects triggered outside change detection now run as part of change detection instead of as a microtask.
Effects triggered during change detection now run earlier, before the component's template.
Errors thrown during ApplicationRef.tick are now rethrown when using TestBed.
ApplicationRef.tickTestBedComponentFixture.whenStablerethrowApplicationErrorsTestBed.configureTestingModule
Zone coalescing and hybrid mode scheduling timers now run in the zone above Angular rather than the root zone.
fakeAsynctickflush
Re-assigns error codes to be within core bounds (<1000).
Sets encapsulation to None for empty component styles.
Change detection timing around custom elements has changed subtly.
Properly resolves tsconfig paths on Windows.
Updates the Resolve interface to include RedirectCommand like ResolveFn.
ResolveRedirectCommandResolveFn
Adds a compiler diagnostic for unused standalone imports.
Adds support for the typeof keyword in template expressions.
typeof
Adds a more specific matcher for the hydrate never block.
Avoids having to duplicate the core environment.
Fixes incorrect projection of control flow nodes with root at the end.
Fixes multiline selectors.
Handles typeof expressions in the serializer.
typeof
Ignores placeholder-only i18n messages.
Resolves :host:host-context(.foo).
:host:host-context(.foo)
Transforms chained pseudo-selectors.
Adds a strictStandalone flag that enforces standalone.
strictStandalone
Ensures template style elements are preprocessed as inline styles.
Generates the HMR replacement module.
Does not fail fatally when references to a non-existent module are discovered.
Does not report unused declarations coming from an imported array.
Fixes incorrectly generating relative file paths on case-insensitive platforms.
Makes the unused imports diagnostic easier to read.
Reports individual diagnostics for unused imports.
Changes effect() execution timing and makes allowSignalWrites a no-op.
effect()allowSignalWrites
Cleans up the event contract once hydration is done.
ComponentFixture autoDetect feature now works like production.
ComponentFixture
Ensures the ViewContext is retained after closure minification.
ViewContext
Fixes issues with control flow and incremental hydration.
Prevents errors on contract cleanup.
Prevents trying to trigger incremental hydration on CSR.
Resolves forward-referenced host directives during directive matching.
Schedulers run in zone above Angular rather than root.
Elements support output()-shaped outputs.
output()
Adds ability to clear a FormRecord.
FormRecord
Fixes FormRecord type inference.
FormRecord
Promotes withRequestsMadeViaParent to stable.
withRequestsMadeViaParent
Preserves all headers from Headers object.
Headers
Adds a combined migration for all signals APIs.
Adds a schematic to migrate to signal queries.
Captures output migration stats.
Exposes output as function migration.
Introduces the signal input migration as an ng generate schematic.
ng generate
Prints output migration stats in ng generate.
ng generate
Replaces .next usage on outputs.
Adds outputs migration to the combined shorthand.
Changes imports to be G3 compatible.
Makes the inject migration always insert generated variables before the super call.
Fixes the inject migration not inserting generated code after super call in some cases.
Migrates more .next output usages.
Properly bundles shared compiler code into migrations.
Properly handles comments in the output migration.
Properly migrates output aliases.
Properly replaces imports across files.
Replaces removed NgModules in tests with their exports.
NgModule
Adds a routerOutletData input to the RouterOutlet directive.
RouterOutletrouterOutletData
Aligns the RouterModule.forRoot error handler with the provider error handler.
RouterModule.forRoot
Allows specifying maxAge for the entire application in the service worker.
maxAge
Finishes the implementation of the service worker refreshAhead feature.
refreshAhead
Errors thrown during ApplicationRef.tick are now rethrown when using TestBed.
ApplicationRef.tickTestBedComponentFixture.whenStablerethrowApplicationErrorsTestBed.configureTestingModule
ComponentFixture autoDetect now attaches the fixture to ApplicationRef, reporting errors to ErrorHandler.
ComponentFixtureApplicationRefErrorHandler
Fixes fixture.detectChanges with autoDetect disabled and zoneless.
fixture.detectChanges
Migrates .pipe calls in outputs used in tests.
Security18
Throws on suspicious URLs and restricts protocol-relative URLs in platform-server.
Sanitizes placeholder values.
Sanitizes dynamic href and xlink:href bindings on SVG a elements.
hrefxlink:href
Strips namespaced SVG script elements during template compilation.
Rejects script element as a dynamic component host.
Sanitizes meta selectors.
Synchronizes core sanitization schema with compiler.
Secures location and document initialization against SSRF and path hijack.
Validates security-sensitive attributes in i18n bindings.
Prevents SSRF bypasses via protocol-relative and backslash URLs in platform-server.
Disallows translations of iframe src attributes in the compiler.
iframesrc
Sanitizes translated attribute bindings that contain interpolations.
Sanitizes translated form attributes.
Blocks creation of sensitive URI attributes from ICU messages.
Sanitizes sensitive attributes on SVG script elements.
Prevents XSS via SVG animation attributeName and MathML/SVG URLs in the compiler.
attributeName
Prevents XSRF token leakage to protocol-relative URLs.
Addresses Trusted Types violations in @angular/upgrade.
@angular/upgrade
Platform5
Supports TypeScript 5.8.
Supports TypeScript 5.7.
TypeScript versions less than 5.5 are no longer supported.
Drops support for TypeScript 5.4.
Adds support for TypeScript 5.6.

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

  • changed: constructor ɵAsyncAnimationRendererFactory(doc: Document, delegate: RendererFactory2, zone: NgZone, animationType: 'animations' | 'noop', moduleImpl?: Promise<{ ɵcreateEngine: (type: 'animations' | 'noop', doc: Document) => ɵAnimationEngine; ɵAnimationRendererFactory: typeof ɵAnimationRendererFactory }> | undefined) → constructor ɵAsyncAnimationRendererFactory(doc: Document, delegate: RendererFactory2, zone: NgZone, animationType: 'animations' | 'noop', moduleImpl?: Promise<{ ɵcreateEngine: (type: 'animations' | 'noop', doc: Document) => _AnimationEngine; ɵAnimationRendererFactory: typeof _AnimationRendererFactory }> | undefined)
  • changed: static property ɵAsyncAnimationRendererFactory.ɵfac: i0.ɵɵFactoryDeclaration<ɵAsyncAnimationRendererFactory, never> → static property ɵAsyncAnimationRendererFactory.ɵfac: i0.ɵɵFactoryDeclaration<AsyncAnimationRendererFactory, never>
  • changed: static property ɵAsyncAnimationRendererFactory.ɵprov: i0.ɵɵInjectableDeclaration<ɵAsyncAnimationRendererFactory> → static property ɵAsyncAnimationRendererFactory.ɵprov: i0.ɵɵInjectableDeclaration<AsyncAnimationRendererFactory>
  • added: protected method ɵAsyncAnimationRendererFactory.componentReplaced(componentId: string): void
  • removed: export { ANIMATION_MODULE_TYPE }
  • changed: class ɵInjectableAnimationEngine extends ɵAnimationEngine implements OnDestroy → class ɵInjectableAnimationEngine extends _AnimationEngine implements OnDestroy
  • changed: constructor ɵInjectableAnimationEngine(doc: Document, driver: AnimationDriver, normalizer: ɵAnimationStyleNormalizer) → constructor ɵInjectableAnimationEngine(doc: Document, driver: AnimationDriver, normalizer: _AnimationStyleNormalizer)
  • changed: static property BrowserAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserAnimationsModule, never, never, [typeof i1.BrowserModule]> → static property BrowserAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserAnimationsModule, never, never, [typeof BrowserModule]>
  • changed: static property NoopAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<NoopAnimationsModule, never, never, [typeof i1.BrowserModule]> → static property NoopAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<NoopAnimationsModule, never, never, [typeof BrowserModule]>
  • changed: static property ɵInjectableAnimationEngine.ɵfac: i0.ɵɵFactoryDeclaration<ɵInjectableAnimationEngine, never> → static property ɵInjectableAnimationEngine.ɵfac: i0.ɵɵFactoryDeclaration<InjectableAnimationEngine, never>
  • changed: static property ɵInjectableAnimationEngine.ɵprov: i0.ɵɵInjectableDeclaration<ɵInjectableAnimationEngine> → static property ɵInjectableAnimationEngine.ɵprov: i0.ɵɵInjectableDeclaration<InjectableAnimationEngine>
  • added: export { ANIMATION_MODULE_TYPE } from '@angular/core'
  • added: class BrowserModule
  • added: const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef
  • added: constructor BrowserModule()
  • added: function bootstrapApplication(rootComponent: Type<unknown>, options?: ApplicationConfig, context?: BootstrapContext): Promise<ApplicationRef>
  • added: function createApplication(options?: ApplicationConfig): Promise<ApplicationRef>
  • added: function provideProtractorTestingSupport(): Provider[]
  • added: interface BootstrapContext
  • added: property BootstrapContext.platformRef: PlatformRef
  • added: static property BrowserModule.ɵfac: i0.ɵɵFactoryDeclaration<BrowserModule, never>
  • added: static property BrowserModule.ɵinj: i0.ɵɵInjectorDeclaration<BrowserModule>
  • added: static property BrowserModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserModule, never, never, [typeof i1.CommonModule, typeof i0.ApplicationModule]>
  • added: type ApplicationConfig = ApplicationConfig$1
  • removed: class BrowserModule
  • removed: const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef
  • removed: const ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS: StaticProvider[]
  • removed: constructor BrowserModule(providersAlreadyPresent: boolean | null)
  • removed: export { ɵgetDOM }
  • removed: function bootstrapApplication(rootComponent: Type<unknown>, options?: ApplicationConfig, context?: BootstrapContext): Promise<ApplicationRef>
  • removed: function createApplication(options?: ApplicationConfig): Promise<ApplicationRef>
  • removed: function provideProtractorTestingSupport(): Provider[]
  • removed: function ɵinitDomAdapter(): void
  • removed: interface BootstrapContext
  • removed: property BootstrapContext.platformRef: PlatformRef
  • removed: readonly property ɵSharedStylesHost.platformId: object
  • removed: static method BrowserModule.withServerTransition(params: { appId: string }): ModuleWithProviders<BrowserModule>
  • removed: static property BrowserModule.ɵfac: i0.ɵɵFactoryDeclaration<BrowserModule, [{ optional: true; skipSelf: true }]>
  • removed: static property BrowserModule.ɵinj: i0.ɵɵInjectorDeclaration<BrowserModule>
  • removed: static property BrowserModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserModule, never, never, [typeof i1.CommonModule, typeof i0.ApplicationModule]>
  • removed: type ApplicationConfig = ApplicationConfig_2
  • changed: abstract method EventManagerPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → abstract method EventManagerPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function
  • changed: class ɵBrowserDomAdapter extends GenericBrowserDomAdapter → class ɵBrowserDomAdapter extends _DomAdapter
  • changed: constructor ɵDomRendererFactory2(eventManager: EventManager, sharedStylesHost: ɵSharedStylesHost, appId: string, removeStylesOnCompDestroy: boolean, doc: Document, platformId: Object, ngZone: NgZone, nonce?: string | null) → constructor ɵDomRendererFactory2(eventManager: EventManager, sharedStylesHost: SharedStylesHost, appId: string, removeStylesOnCompDestroy: boolean, doc: Document, platformId: Object, ngZone: NgZone, nonce?: string | null, tracingService?: _TracingService<_TracingSnapshot> | null)
  • changed: constructor ɵHammerGesturesPlugin(doc: any, _config: HammerGestureConfig, console: ɵConsole, loader?: (HammerLoader | null) | undefined) → constructor ɵHammerGesturesPlugin(doc: any, _config: HammerGestureConfig, _injector: Injector, loader?: (HammerLoader | null) | undefined)
  • changed: constructor ɵSharedStylesHost(doc: Document, appId: string, nonce?: (string | null) | undefined, platformId?: object) → constructor ɵSharedStylesHost(doc: Document, appId: string, nonce?: string | null | undefined, platformId?: object)
  • changed: method EventManager.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method EventManager.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function
  • changed: method ɵBrowserDomAdapter.onAndCancel(el: Node, evt: any, listener: any): Function → method ɵBrowserDomAdapter.onAndCancel(el: Node, evt: any, listener: any, options: any): Function
  • changed: method ɵDomEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method ɵDomEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function
  • changed: method ɵDomEventsPlugin.removeEventListener(target: any, eventName: string, callback: Function): void → method ɵDomEventsPlugin.removeEventListener(target: any, eventName: string, callback: Function, options?: ListenerOptions): void
  • changed: method ɵKeyEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method ɵKeyEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function
  • changed: method ɵSharedStylesHost.addStyles(styles: string[]): void → method ɵSharedStylesHost.addStyles(styles: string[], urls?: string[]): void
  • changed: method ɵSharedStylesHost.removeStyles(styles: string[]): void → method ɵSharedStylesHost.removeStyles(styles: string[], urls?: string[]): void
  • changed: static property ɵDomEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomEventsPlugin, never> → static property ɵDomEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<DomEventsPlugin, never>
  • changed: static property ɵDomEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomEventsPlugin> → static property ɵDomEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<DomEventsPlugin>
  • changed: static property ɵDomRendererFactory2.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomRendererFactory2, never> → static property ɵDomRendererFactory2.ɵfac: i0.ɵɵFactoryDeclaration<DomRendererFactory2, [null, null, null, null, null, null, null, null, { optional: true }]>
  • changed: static property ɵDomRendererFactory2.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomRendererFactory2> → static property ɵDomRendererFactory2.ɵprov: i0.ɵɵInjectableDeclaration<DomRendererFactory2>
  • changed: static property ɵDomSanitizerImpl.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomSanitizerImpl, never> → static property ɵDomSanitizerImpl.ɵfac: i0.ɵɵFactoryDeclaration<DomSanitizerImpl, never>
  • changed: static property ɵDomSanitizerImpl.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomSanitizerImpl> → static property ɵDomSanitizerImpl.ɵprov: i0.ɵɵInjectableDeclaration<DomSanitizerImpl>
  • changed: static property ɵHammerGesturesPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵHammerGesturesPlugin, [null, null, null, { optional: true }]> → static property ɵHammerGesturesPlugin.ɵfac: i0.ɵɵFactoryDeclaration<HammerGesturesPlugin, [null, null, null, { optional: true }]>
  • changed: static property ɵHammerGesturesPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵHammerGesturesPlugin> → static property ɵHammerGesturesPlugin.ɵprov: i0.ɵɵInjectableDeclaration<HammerGesturesPlugin>
  • changed: static property ɵKeyEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵKeyEventsPlugin, never> → static property ɵKeyEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<KeyEventsPlugin, never>
  • changed: static property ɵKeyEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵKeyEventsPlugin> → static property ɵKeyEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<KeyEventsPlugin>
  • changed: static property ɵSharedStylesHost.ɵfac: i0.ɵɵFactoryDeclaration<ɵSharedStylesHost, [null, null, { optional: true }, null]> → static property ɵSharedStylesHost.ɵfac: i0.ɵɵFactoryDeclaration<SharedStylesHost, [null, null, { optional: true }, null]>
  • changed: static property ɵSharedStylesHost.ɵprov: i0.ɵɵInjectableDeclaration<ɵSharedStylesHost> → static property ɵSharedStylesHost.ɵprov: i0.ɵɵInjectableDeclaration<SharedStylesHost>
  • added: export { ApplicationConfig } from './browser.d-[hash]'
  • added: export { BootstrapContext } from './browser.d-[hash]'
  • added: export { BrowserModule } from './browser.d-[hash]'
  • added: export { bootstrapApplication } from './browser.d-[hash]'
  • added: export { createApplication } from './browser.d-[hash]'
  • added: export { platformBrowser } from './browser.d-[hash]'
  • added: export { provideProtractorTestingSupport } from './browser.d-[hash]'
  • added: export { ɵgetDOM } from '@angular/common'
  • added: function withIncrementalHydration(): HydrationFeature<HydrationFeatureKind.IncrementalHydration>
  • added: member HydrationFeatureKind.IncrementalHydration = 4
  • added: protected method ɵDomRendererFactory2.componentReplaced(componentId: string): void
  • added: protected method ɵSharedStylesHost.addUsage<T extends HTMLElement>(value: string, usages: Map<string, UsageRecord<T>>, creator: (value: string, doc: Document) => T): void
  • added: protected method ɵSharedStylesHost.removeUsage<T extends HTMLElement>(value: string, usages: Map<string, UsageRecord<T>>): void
  • added: readonly property ɵBrowserDomAdapter.supportsDOMEvents: boolean
  • changed: static property BrowserTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserTestingModule, never, never, [typeof i1.BrowserModule]> → static property BrowserTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserTestingModule, never, never, [typeof BrowserModule]>