20.0.0
Blog post: https://blog.angular.dev/announcing-angular-v20-b5c9c06cf301
common
Commit | Description |
---|---|
accept undefined inputs in NgTemplateOutlet (#61404) | |
Allow passing ScrollOptions to ViewportScroller (#61002) | |
throw error for suspicious date patterns (#59798) | |
cleanup updateLatestValue if view is destroyed before promise resolves (#58041) |
|
Handle errors in async pipe subscriptions (#60057) | |
issue a warning instead of an error when NgOptimizedImage exceeds the preload limit (#60879) |
|
rename httpResource function in factory (#60022) | |
resolve host binding type issues (#60481) |
compiler
Commit | Description |
---|---|
add extended diagnostic for uninvoked track function on @for blocks (#60495) |
|
support exponentiation operator in templates (#59894) | |
support tagged template literals in expressions (#59947) | |
support the in keyword in Binary expression (#58432) |
|
support void operator in templates (#59894) | |
error if rawText isn't estimated correctly (#60529) | |
exponentiation should be right-to-left associative (#60101) | |
incorrect spans for template literals (#60323) | |
incorrectly handling let declarations inside i18n (#60512) | |
proper handling of typeof, void in RecursiveAstVisitor (#60101) | |
remove TypeScript from linker (#61635) | |
reduce allocations for let declarations only used in the same view (#60512) |
compiler-cli
Commit | Description |
---|---|
add extended diagnostic for invalid nullish coalescing (#60279) | |
detect missing structural directive imports (#59443) | |
support type checking of host bindings (#60267) | |
avoid fatal diagnostics for invalid module schemas (#61220) | |
avoid fatal diagnostics for missing template files (#58673) | |
correctly parse event name in HostListener (#60561) | |
preserve required parens for nullish coalescing (#60060) | |
preserve required parens in exponentiation expressions (#60101) | |
set correct target when type checking events (#60561) | |
wrong event name for host listener decorators (#60460) |
core
Commit | Description |
---|---|
add hook for producer creation side effects (#60333) | |
add input binding support to dynamically-created components (#60137) | |
Add provider which reports unhandled errors on window to ErrorHandler (#60704) | |
add support for two-way bindings on dynamically-created components (#60342) | |
add the ability to apply directives to dynamically-created components (#60137) | |
drop support for TypeScript older than 5.8 (#60197) | |
emit template function for template related profiler hooks (#60174) | |
export signalGetFn from signal primitives (#60497) | |
Expose Injector.destroy on Injector created with Injector.create (#60054) |
|
expose performance data in Chrome DevTools (#60789) | |
introduce new DI profiling event (#60158) | |
introduce TestBed.tick() (#60993) | |
mark toObservable as stable (#60449) |
|
mark linkedSignal API as public (#60865) | |
mark the toSignal API as stable (#60442) | |
move provideExperimentalCheckNoChangesForDebug to provideCheckNoChangesConfig (#60906) |
|
move DOCUMENT token into core (#60663) | |
Move zoneless change detection to dev preview (#60748) | |
remove InjectFlags from public API (#60318) | |
remove TestBed.get (#60414) | |
rename afterRender to afterEveryRender and stabilize (#60999) | |
stabilize incremental hydration api (#60888) | |
stabilize linkedSignal API (#60741) | |
Stabilize PendingTasks Injectable (#60716) | |
stabilize withI18nSupport() api (#60889) | |
support listening to outputs on dynamically-created components (#60137) | |
update Node.js version support (#60545) | |
add migration away from InjectFlags (#60318) | |
added @angular/compiler as a peer dependency (#55610) | |
call DestroyRef on destroy callback if view is destroyed (#58008) |
|
Catch and report rejections in async function of PendingTasks.run (#60044) |
|
defer block render failures should report to application error handler (#60149) | |
do not allow setInput to be used with inputBinding (#60137) | |
do not run change detection on global error events (#60944) | |
enable stashing only when withEventReplay() is invoked (#61077) |
|
Ensure ComponentFixture does not duplicate error reporting from FakeAsync (#60104) | |
Ensure errors in listeners report to the application error handler (#60251) | |
fix typing on injector.get to omit 'any' (#60202) | |
fixes timing of hydration cleanup on control flow (#60425) | |
Flush animations when no component has been checked (#58089) | |
getting resource value throws an error instead of returning undefined (#61441) | |
handle different DI token types in Chrome DevTools integration (#61333) | |
inject migration should treat @Attribute as optional (#60916) |
|
input targeting not checking if input exists on host (#60137) | |
mark zone.js as an optional peer dependency (#61616) |
|
move reload method from Resource to WritableResource (#61441) | |
narrow error type for resources API (#61441) | |
prevent stash listener conflicts (#59635) | |
properly handle app stabilization with defer blocks (#61040) | |
reading resource value after reload in the error state (#61441) | |
reduce total memory usage of various migration schematics (#60774) | |
release hasPendingTasks observers (#59723) |
|
remove forceRoot flag for effects (#60535) |
|
remove rejectErrors option encourages uncaught exceptions (#60397) |
|
Remove duplicate reporting of errors in CDR.detectChanges (#60056) |
|
remove unused parameter from listener instruction (#60406) | |
run ApplicationRef.prototype.bootstrap in NgZone (#60720) |
|
run root effects in creation order (#60534) | |
Surface errors from ApplicationRef.tick to callsite (#60102) |
|
TestBed.tick should ensure test components are synchronized (#61382) | |
Testing should not throw when Zone does not patch test FW APIs (#61628) | |
update min Node.js support to 20.19, 22.12, and 24.0 (#61500) | |
Deprecate the structural directives ngIf /ngFor /ngSwitch . (#60492) |
|
stop producing ng-reflect attributes by default (#60973) |
forms
Commit | Description |
---|---|
add markAllAsDirty to AbstractControl (#58663) | |
Allow to reset a form without emitting events (#60354) | |
Make sure statusChanges is emitted (#57098) | |
resolve host binding type issues (#60481) |
http
Commit | Description |
---|---|
add keepalive support for fetch requests (#60621) | |
Delay stabilization until next app synchronization (#60656) |
platform-browser
Commit | Description |
---|---|
Deprecate the platform-browser-dynamic package (#61043) |
|
Deprecate the HammerJS integration (#60257) |
platform-server
Commit | Description |
---|---|
deprecate the testing entry point (#60915) |
router
Commit | Description |
---|---|
Add ability to directly abort a navigation (#60380) | |
add asynchronous redirects (#60863) | |
Allow resolvers to read resolved data from ancestors (#59860) | |
support custom elements for RouterLink (#60290) | |
Prevent dangling promise rejections from internal navigations (#60162) | |
relax required types on router commands to readonly array (#60345) | |
Remove 'any' type from route guards (#60378) | |
Scroller should scroll as soon as change detection completes (#60086) |
Breaking Changes
common
- Using the
Y
formatter (week-numbering year) without also includingw
(week number) is now detected as suspicious date pattern, asy
is typically intended. AsyncPipe
now directly catches unhandled errors in
subscriptions and promises and reports them to the application's
ErrorHandler
. For Zone-based applications, these errors would have
been caught by ZoneJS and reported toErrorHandler
so the result is
generally the same. The change to the exact mechanism for reporting can
result in differences in test environments that will require test
updates.
compiler
-
'in' in an expression now refers to the operator
-
void
in an expression now refers to the operatorPreviously an expression in the template like
{{void}}
referred to a
property on the component class. After this change it now refers to the
void
operator, which would make the above example invalid. If you have
existing expressions that need to refer to a property namedvoid
,
change the expression to usethis.void
instead:{{this.void}}
.
core
-
- TypeScript versions less than 5.8 are no longer supported.
-
the
TestBed.flushEffects()
was removed - use
theTestBed.tick()
instead. -
provideExperimentalCheckNoChangesForDebug
has several
breaking changes:- It is renamed to
provideCheckNoChangesConfig
- The behavior applies to all checkNoChanges runs
- The
useNgZoneOnStable
option is removed. This wasn't found to be generally
more useful thaninterval
- It is renamed to
-
provideExperimentalZonelessChangeDetection
is
renamed toprovideZonelessChangeDetection
as it is now "Developer
Preview" rather than "Experimental". -
InjectFlags
has been removed.inject
no longer acceptsInjectFlags
.Injector.get
no longer acceptsInjectFlags
.EnvironmentInjector.get
no longer acceptsInjectFlags
.TestBed.get
no longer acceptsInjectFlags
.TestBed.inject
no longer acceptsInjectFlags
.
-
TestBed.get
has been removed. UseTestBed.inject
instead.
-
afterRender was renamed to afterEveryRender.
-
- Angular no longer supports Node.js v18.
- Node.js versions 22.0 to 22.10 are also no longer supported.
Before upgrading to Angular v20, ensure the Node.js version is at least 20.11.1.
For the full list of supported versions, visit: https://angular.dev/reference/versions -
PendingTasks.run
no longer returns the result of the
async function. If this behavior is desired, it can be re-implemented
manually with thePendingTasks.add
. Be aware, however, that promise rejections
will need to be handled or they can cause the node process to shut down
when using SSR. -
Uncaught errors in listeners which were previously only reported to
ErrorHandler
are now also reported to Angular's internal error
handling machinery. For tests, this means that the error will be
rethrown by default rather than only logging the error. Developers
should fix these errors, catch them in the test if the test is
intentionally covering an error case, or userethrowApplicationErrors: false
inconfigureTestingModule
as a last resort. -
The
any
overload has been removed from
injector.get
. It now only supportsProviderToken<T>
and (deprecated
since v4)string
. -
Animations are guaranteed to be flushed when Angular
runs automatic change detection or manual calls toApplicationRef.tick
.
Prior to this change, animations would not be flushed in some situations
if change detection did not run on any views attached to the
application. This change can affect tests which may rely on the old
behavior, often by making assertions on DOM elements that should have
been removed but weren't because DOM removal is delayed until animations
are flushed. -
ApplicationRef.tick
will no longer catch and report
errors to the appplicationErrorHandler
. Errors will instead be thrown out of
the method and will allow callers to determine how to handle these
errors, such as aborting follow-up work or reporting the error and
continuing. -
This commit deprecates
ng-reflect-*
attributes and updates the runtime to stop producing them by default. Please refactor application and test code to avoid relying onng-reflect-*
attributes.To enable a more seamless upgrade to v20, we've added the
provideNgReflectAttributes()
function (can be imported from the@angular/core
package), which enables the mode in which Angular would be producing those attribites (in dev mode only). You can add theprovideNgReflectAttributes()
function to the list of providers within the bootstrap call.
router
- The
RedirectFn
can now returnObservable
or
Promise
. Any code that directly calls functions returning this type
may need to be adjusted to account for this. - Several methods in the public API of the Router which
required writable arrays have now been updated to accept readonly
arrays when no mutations are done. - The guards arrays on
Route
no longer includeany
in
the type union. The union includes functions for the functional guards
as well as a type matchingInjector.get
:ProviderToken<T>|string
.
Note that string is still deprecated on both the route guards and
Injector.get
.
Deprecations
core
ngIf
/ngFor
/ngSwitch
are deprecated. Use the control flow blocks instead (@for
/@if
/@switch
).
platform-browser
- All entries of the
@angular/platform-browser-dynamic
- HammerJS support is deprecated and will be removed in a future major version.
platform-server
-
@angular/platform-server/testing
Use e2e tests to verify SSR behavior instead.