We were clearing duplicate nodes when `animate.enter` fired fast, but not when solely `animate.leave` is fired and rapid toggles occur. This ensures that the `cancelLeavingNodes` function is called in all cases instead of just enter animations.
fixes: #64581
PR Close#64592
Previously, query parameters passed to `router.createUrlTree` were simply converted to strings. This meant that any custom serialization logic in a custom `UrlSerializer` was not applied. This could lead to inconsistencies between navigations triggered from the URL bar (which are parsed by the serializer) and navigations triggered programmatically.
This change ensures that query parameters are normalized using the provided `UrlSerializer`. The values are serialized and then parsed to ensure they are in the same format as if they had come from a URL. This allows custom serializers to handle complex objects in query parameters consistently.
Fixes https://github.com/angular/angular/issues/47307
PR Close#64449
Currently it's easy to make a mistake when accessing properties on `SimpleChanges`, because the keys aren't typed. These changes add an optional generic to the interface so that users can get a compilation error if they make a typo.
A few things to note:
1. The generic argument is optional and we revert to the old behavior if one isn't passed for backwards compatibility.
2. All of the keys are optional, because they aren't guaranteed to be present for any `ngOnChanges` invocation.
3. We unwrap the values of input signals to match the behavior at runtime.
Fixes#17560.
PR Close#64535
Previously, query parameters passed to `router.createUrlTree` were simply converted to strings. This meant that any custom serialization logic in a custom `UrlSerializer` was not applied. This could lead to inconsistencies between navigations triggered from the URL bar (which are parsed by the serializer) and navigations triggered programmatically.
This change ensures that query parameters are normalized using the provided `UrlSerializer`. The values are serialized and then parsed to ensure they are in the same format as if they had come from a URL. This allows custom serializers to handle complex objects in query parameters consistently.
Fixes https://github.com/angular/angular/issues/47307
PR Close#64449
In some rare cases, it seems the animation queue disappears despite being afterEveryRender. This updates the animation scheduler to be afterNextRender instead and only schedules it when we need to.
fixes: #64423
PR Close#64441
When adding and removing items in a `@for` loop, the `animate.leave` event binding instruction was not updated to use the same logic as the class function when the animation queue was added. We were not returning the correct signature for the `animate.leave` function, which caused the animation to not trigger correctly. This updates the event binding instruction to use the same logic as the class function when adding the animation to the queue.
fixes: #64336
PR Close#64413
This commit adds `applicationProviders` to the `bootstrapModule` options
object. This allows specifying additional providers at the location of
bootstrap, which makes default providers much easier to accomplish.
Using this, we can refine the approach taken for downgrade_module to use
this more direct API rather than the additional provider variable dance.
PR Close#64354
This fixes the code to retain ZoneJS by default in the providers for
downgradeModule when the `bootstrapModule` is used. Prior to this
change, the async `bootstrapModule`/`compileNgModuleFactory` could be
called multiple times through `downgradeModule` before
`bootstrapModuleFactory` got called and used the zone providers.
Note: marked refactor since this only applies to the -next release and
we shouldn't have this change in the changelog as a fix.
PR Close#64354
This simplifies code by using async/await instead of rxjs in the config
loading internals. While loadChildren/loadComponent could _technically_
return a synchronous value, the expectation is that this would be used
for dynamic imports, which are necessarily async.
PR Close#64322
Renames the control directive and the input that users set to bind a
field to a UI control.
Previously users would do:
```
<input [control]="someField">
```
Now users will do:
```
<input [filed]="someField">
```
PR Close#64300
Adds support for customizing the `IntersectionObserver` options for the `on viewport`, `prefetch on viewport` and `hydrate on viewport` triggers.
Note that the options need to be a static object literal, e.g. `@defer (on viewport(trigger, {rootMargin: '123px'})`.
Fixes#52799.
PR Close#64130
Our code ensuring host binding composition for animations was causing the early exit and removal of
elements when multiple transitions were present on the same element. This commit fixes the issue by
ensuring that we properly keep track of all the promise resolvers on the LView and then only
call them once we've properly waited for the longest animation to finish.
fixes: #64209
PR Close#64225
These tests were not properly validating against the host binding changes due to the fact that the styles were on the wrong components in some of the host binding cases.
PR Close#64225
* Emit a `ɵɵcontrol` instruction in place of `ɵɵproperty` for property
bindings named "control". This instruction cannot be chained, but is
otherwise functionally equivalent.
* Upcoming changes will use the `ɵɵcontrol` instruction to bind a signal
form field to a UI control (be it a native element or custom directive).
PR Close#63773
This commit updates the internal transition to handle context retention
through the abort function. This retention chain included the
previousNavigation and setting this to a noop function resolves the
issue.
fixes#63983
PR Close#64141
Content Projected nodes are not destroyed and recreated, like every other
situation. Enter and Leave animations were ephemeral and are
expected to run once, and then be cleared. This means that for content projection
cases, the animations would only ever work the first time they were shown / hid.
In order to resolve this, we move to an animation queue that re-runs the animation
functions stored in the LView. In most cases, this animation will run once on creation.
For content projection, the enter and leave animations will fire more than once. Animations
are stored on the LView, but indexed and scheduled by whichever RNode needs to be animated.
So we only run animations for an affected RNode, rather than potentially all in the LView.
This also moves the queue to afterRender, which is safer than right after template
execution in refreshView.
fixes: #63418fixes: #64065fixes: #63901
PR Close#63776
Content Projected nodes are not destroyed and recreated, like every other
situation. Enter and Leave animations were ephemeral and are
expected to run once, and then be cleared. This means that for content projection
cases, the animations would only ever work the first time they were shown / hid.
In order to resolve this, we move to an animation queue that re-runs the animation
functions stored in the LView. In most cases, this animation will run once on creation.
For content projection, the enter and leave animations will fire more than once. Animations
are stored on the LView, but indexed and scheduled by whichever RNode needs to be animated.
So we only run animations for an affected RNode, rather than potentially all in the LView.
This also moves the queue to afterRender, which is safer than right after template
execution in refreshView.
fixes: #63418fixes: #64065fixes: #63901
PR Close#63776
The event listeners for animationstart and animationend weren't properly checking whether the animation event fired matched the node we're bound to, since animation events bubble. This resulted in child node animation events bubbling up and causing elements to get prematurely removed.
fixes: #64084
PR Close#64088
This commit changes `Resource.hasValue()` and its derived types to improve narrowing
of resources whose generic type either does not include `undefined` (i.e. when a default
value has been provided) or when the generic type is `unknown`. This fixes the undesirable
behavior where `hasValue()` would cause the `else` branch of an `hasValue()` conditional
to have a narrowed type of `never`, given that the `hasValue()`'s type guard covers the
entire type range already (meaning that the type in the else-branch cannot be inhabited
in the type system, yielding the `never` type).
By making the `hasValue()` method only a type guard when the generic type includes `undefined`
these problems are avoided.
Fixes#60766Fixes#63545Fixes#63982
PR Close#63994
This adds an optional flag to the renderer on `removeChild` called `requireSynchronousElementRemoval`, which can tell any downstream renderer that elements need to be removed synchronously. This gets passed down to the legacy animation renderer to ensure that any elements that set this flag aren't impacted by that renderers changes to timing.
fixes: #63893
PR Close#63921
https://github.com/angular/angular/pull/62630 made it so that all ARIA
property bindings would write to their corresponding attribute instead.
The primary motivation for this change was to ensure that ARIA
attributes were always rendered correctly on the server, where the
emulated DOM may not correctly reflect ARIA properties as attributes.
Furthermore, this change added support for binding to ARIA attributes
using the property binding syntax (e.g. `[aria-label]`).
Unfortunately, https://github.com/angular/angular/pull/62630 relied on
the incorrect assumptions that an ARIA property name could be converted
to its attribute name (without hardcoding the conversion), and that the
value of an ARIA property matched its corresponding attribute. For
example, the `ariaLabelledByElements` property's value is an array of
DOM elements, while the corresponding `aria-labelledby` attribute's
value is a string containing the IDs of the DOM elements.
This partially reverts https://github.com/angular/angular/pull/62630 so
that only property bindings with ARIA attribute names (begin with
`aria-`) are converted to attribute bindings.
* `[ariaLabel]` will revert to binding to the `ariaLabel` property.
* `[aria-label]` will continue binding to the `aria-label` attribute.
Note the only difference between `[aria-label]` and `[attr.aria-label]`
is that the former will attempt to bind to inputs of the same name while
the latter will not.
PR Close#63925
Previously, HOST_TAG_NAME had its __NG_ELEMENT_ID__ set at the top level. This
prevented tree-shaking, since the bundler had to keep the assignment as a
potential side effect even when the token was never used.
This change moves the token creation and __NG_ELEMENT_ID__ assignment into a
@__PURE__ IIFE. If HOST_TAG_NAME is not injected anywhere, the IIFE result is
unused and can be dropped entirely by the optimizer. If it is used, the token
still behaves the same at runtime.
PR Close#63861
This makes the zoneless-by-default change a flag flip that can be
individually enabled in tests, createApplication, and bootstrapModule
for gradual rollout. In addition, the "require on CD provider" check is
also made individually flippable for gradual rollout.
PR Close#63382
This change removes the internally provided `ZoneJS`-based change
detection scheduler. This makes Angular Zoneless by default and allows
tree-shaking of the Zone change detection providers.
BREAKING CHANGE: Angular no longer provides a change detection scheduler
for ZoneJS-based change detection by default. Add
`provideZoneChangeDetection` to the providers of your
`bootstrapApplication` function or your `AppModule` (if using
`bootstrapModule`). This provider addition will be covered by an
automated migration.
PR Close#63382
In production builds, `ngDevMode` is replaced with `false`, so the guard compiles to `return;`. However, bundlers like ESBuild still keep the remaining statements after the return as unreachable code instead of removing them. This leaves behind unnecessary dead code in the output.
Technically, the body is unreachable. But to prove that, the bundler must be 100% certain that:
- `return` cannot be removed by some transform
- there's no later transformation that changes control flow
As thus, it's always conservative.
This also allows dropping `assertDefined`, which was previously
referenced only inside `prependTokenToDependencyPath`. With the
function now fully inlined and dev-only, `assertDefined` is also
eliminated from production builds, further reducing bundle size.
PR Close#63354
To avoid the need for specifying `provideZoneChangeDetection` in any/all
modules used with `downgradedModule`, this change adds the zone-based change detection
providers by default. This also adds the zone providers to
`UpgradeModule` by default as well.
PR Close#63814
The `checkNoChanges` method previously used an early-return guard:
if (!ngDevMode) return;
// dev-only code ...
In production builds, `ngDevMode` is replaced with `false`, so the
guard compiles to `return;`. However, bundlers like ESBuild
still keep the remaining statements after the return as unreachable
code instead of removing them. This leaves behind unnecessary dead
code in the output.
This commit updates the method to instead wrap the full body:
if (ngDevMode) {
// dev-only code ...
}
With this change, the method collapses to an empty function in
production builds:
checkNoChanges() {}
This ensures that the dev-only logic and its dependencies
(e.g. `checkNoChangesInternal`, `UseExhaustiveCheckNoChanges`) can be
fully tree-shaken, reducing bundle size.
PR Close#63387
This option was deprecated by #55778.
BREAKING CHANGE: The `interpolation` option on Components has been removed. Only the default `{{ ... }}` is now supported.
PR Close#63474