This is a pure re-organization of the animations code. No functionality changes, but it should be easier to navigate now. Utility classes have been moved to a `utils.ts` file. The related functions in the instructions have been grouped closer together.
PR Close#63775
When a user has `animate.leave` on a list of items in a `@for`, but are only showing a subset using a computed, removing the second to last item results in a move operation on the last item. There's no native atomic move API in the browser. So this results in the element being detached and attached at its new index. The detaching of the node resulted in leave animations firing.
This fix addresses this by adding a flag in the `LView[ANIMATIONS]` `AnimationLViewData` interface to allow for skipping animations. During list reconciliation, we set this flag so that the animations are skipped over. The flag is flipped back after the move operation is complete.
There is one complication that results from this. The index adjustment of elements in the list happens synchronously while the leave animation is asynchronous. This results in the leaving item getting shifted to the end of the list. This is not ideal but likely can be addressed in a future refactor.
fixes: #63544
PR Close#63745
This updates the enter and leave logic to use the stored LView data to dispatch the enter and leave animations at the right points in the lifecycle. This should fix issues with signals not being available yet, parallel animations, and also eliminate the need for the element registry.
fixes: #63391fixes: #63388fixes: #63369
PR Close#63710
In order to point the right context, links in error messages will target the archived version of the online doc site (v*.angular.io).
See #44650
PR Close#63512
This will allow manually subscribed animation events to still fire when using `animate.leave`. Otherwise they were being cleaned up before the animations happened.
fixes: #63391
PR Close#63414
This commit introduces a number of changes to the server bootstrapping process to make it more robust and less error-prone, especially for concurrent requests.
Previously, the server rendering process relied on a module-level global platform injector. This could lead to issues in server-side rendering environments where multiple requests are processed concurrently, as they could inadvertently share or overwrite the global injector state.
The new approach introduces a `BootstrapContext` that is passed to the `bootstrapApplication` function. This context provides a platform reference that is scoped to the individual request, ensuring that each server-side render has an isolated platform injector. This prevents state leakage between concurrent requests and makes the overall process more reliable.
BREAKING CHANGE:
The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.
Before:
```ts
const bootstrap = () => bootstrapApplication(AppComponent, config);
```
After:
```ts
const bootstrap = (context: BootstrapContext) =>
bootstrapApplication(AppComponent, config, context);
```
A schematic is provided to automatically update `main.server.ts` files to pass the `BootstrapContext` to the `bootstrapApplication` call.
In addition, `getPlatform()` and `destroyPlatform()` will now return `null` and be a no-op respectively when running in a server environment.
(cherry picked from commit 8bf80c9d2314b4f2bcf3df83ae01552a6fc49834)
PR Close#63636
This commit updates provider definitions that relied on the `deps` array
with `new Optional()` and `new SkipSelf()` to instead use the modern
`inject(..., { optional: true, skipSelf: true })` API.
Previously:
deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
Now:
const parent = inject(KeyValueDiffers, { optional: true, skipSelf: true });
**Bundle size reduction**: `Optional` and `SkipSelf` are runtime values
created by `makeParamDecorator()`. Even in production builds, esbuild
and other bundlers must keep their factory code because they are
referenced with `new Optional()` / `new SkipSelf()`. With `inject()`,
those classes are no longer referenced, allowing them and the
`makeParamDecorator` scaffolding to be tree-shaken when unused.
As a result, production bundles can drop both `Optional`, `SkipSelf`, and
their supporting factory code when not used elsewhere, reducing code size
while keeping the same behavior.
PR Close#63386
When toggling visibility on an element over and over, the enter animations were supposed to be cancelled and then the classes removed. There was a race condition happening that resulted in the cancelled animation being the leave animation. Rather than using the animation.cancel functionality, it's safer to just remove the enter classes.
fixes: #63439
PR Close#63442
Annotate the `new Version(...)` call with `/* @__PURE__ */` to signal to
optimizers that the constructor is side-effect free.
Without this hint, bundlers such as Terser or ESBuild may conservatively
retain the `VERSION` instantiation even when unused. With the annotation,
the constant can be tree-shaken away in production builds if not referenced,
reducing bundle size.
PR Close#63400
This commit prevents lazy injection of the internal `ErrorHandler` from a destroyed injector, which would otherwise result in a secondary "destroyed injector" error.
The `handleUncaughtError` function is used in a wrapped event listener that invokes the `ErrorHandler` if the listener throws. A simple case in a micro-frontend application:
```ts
onNavigationToAnotherApp() {
this.appRef.destroy();
do_some_stuff_ie_loggin_that_may_throw();
}
```
If the function throws an error, Angular attempts to inject the `ErrorHandler` from a destroyed injector.
PR Close#62275
When declaring directives, the standalone flag is set to true by default in current Angular versions.
The docs for the directive decorator should correctly explain the default behavior, while still mentioning when to set it to false.
PR Close#63329
The 4 second removal timeout was applying in all cases, but it should only actually apply to the situation where the event binding syntax is used for animate.leave. This ensures that's the only case in which it'll apply.
PR Close#63393
The animate instructions were getting applied to the container comment nodes as well as the element nodes. This prevents that on the compiler level.
fixes: #63371
PR Close#63390
This fixes the rare case that someone uses binding syntax with `animate.leave` providing a value with a string that has spaces in it. For example:
```
<example `[animate.leave]="'class-a class-b"` />
```
fixes: #63365
PR Close#63366
There's special logic in place to prevent duplicate nodes from showing up in the case when an `@if` toggles a view quickly. This had the unfortunate side effect of causing `@for` leave animations to get cancelled when an add and remove happened simultaneously, even if it was a different index. This fix prevents that from happening in the `@for` loop case.
fixes: #63307
PR Close#63328
In the case that someone wants to disable animations via selector specificity, for example by adding an `.animate-disabled` class to a parent node, we need to make sure the animate instructions don't misbehave. Now we detect if animations exist in the provided classes and react accordingly.
fixes: #63161
PR Close#63242
Ensure consistency in error message wording by aligning the NG0303
error with other Angular error strings. This improves clarity and
maintains a uniform developer experience
PR Close#63222
This applies the same fix that fixed the class version to the event binding version. It prevents duplicate elements from being on screen when animations have been toggled too fast.
fixes: #63127
PR Close#63216
This commit extracts helper functions to reduce code duplication across animation instructions and adds early return when animations are disabled.
PR Close#63163
In the case that a leave animation is running and someone toggles an `@if`, a new node would be inserted. For a brief moment, there may be two of the same nodes visible at once. While this is expected with native CSS, it's not ideal. Instead, we retain a reference to the leaving element and can remove that node when the new node is entering.
fixes: #63020
PR Close#63048
This deprecates `BootstrapOptions` since `NgZone` can now be configured
in the providers. This is a necessary step because when zoneless becomes
the default, developers will have to add ZoneJS via
`provideZoneChangeDetection` and that will override anything defined in
`BootstrapOptions`.
PR Close#62690
Any time something causes styles to recalculate,
`element.getAnimations()` will be empty. This updates `animate.enter`
and `animate.leave` to rely on `getComputedStyles` to determine the
longest animation instead.
fixes: #63006
PR Close#63007
Adds an internal token to detect when both hydration and blocking initial navigation are enabled. Logs a warning during app initialization if this unsupported combination is found, helping developers avoid misconfiguration and potential runtime issues.
PR Close#62963
Currently when loading external resources in JIT, when `fetch` fails,
the `text` is empty and the component is loading. This hides the actual
underlying fetch error. We should properly detect this and error out.
PR Close#62992
In the case when composing animation classes with `animate.enter` on the
element itself and also with host bindings, the removal would only
have context for one of the classes added: the last one added. This
allows for tracking of the classes added by `animate.enter` via a
WeakMap so we know the exact classes added and which to remove.
Also shores up the tests to make sure we are fully testing animate.enter.
PR Close#62981
Space separated strings, e.g. `class-1 class-2`, should work with both enter and leave animations. `animate.leave` lost that functionality in a refactor. Tests are now added to catch this.
fixes: #62964
PR Close#62979
When animate.leave is used, stylesheet pruning causes issues. Stylesheets with the appropriate animations get pruned before the animations can run. This will delay the removal in the case that the registry is present.
fixes: #62942
PR Close#62943
In some patterns, `element.getAnimations()` will be an empty array despite the animation class being present during animation start and the style sheet showing a keyframe animation.
Moving the longest animation check to the end resolves this problem.
fixes: #62923
PR Close#62925
This adds a test module configuration to define whether animations should be enabled or disabled in test. By default, they are disabled.
PR Close#62764