mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(core): prevent duplicate nodes from being retained with fast animate.leave` calls (#64592)
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
This commit is contained in:
@@ -68,7 +68,6 @@ export function ɵɵanimateEnter(value: string | Function): typeof ɵɵanimateEn
|
||||
}
|
||||
|
||||
const tNode = getCurrentTNode()!;
|
||||
|
||||
cancelLeavingNodes(tNode, lView);
|
||||
|
||||
addAnimationToLView(getLViewEnterAnimations(lView), tNode, () =>
|
||||
@@ -196,7 +195,6 @@ export function ɵɵanimateEnterListener(value: AnimationFunction): typeof ɵɵa
|
||||
return ɵɵanimateEnterListener;
|
||||
}
|
||||
const tNode = getCurrentTNode()!;
|
||||
|
||||
cancelLeavingNodes(tNode, lView);
|
||||
|
||||
addAnimationToLView(getLViewEnterAnimations(lView), tNode, () =>
|
||||
@@ -251,6 +249,7 @@ export function ɵɵanimateLeave(value: string | Function): typeof ɵɵanimateLe
|
||||
}
|
||||
|
||||
const tNode = getCurrentTNode()!;
|
||||
cancelLeavingNodes(tNode, lView);
|
||||
|
||||
addAnimationToLView(getLViewLeaveAnimations(lView), tNode, () =>
|
||||
runLeaveAnimations(lView, tNode, value),
|
||||
@@ -383,6 +382,8 @@ export function ɵɵanimateLeaveListener(value: AnimationFunction): typeof ɵɵa
|
||||
|
||||
const lView = getLView();
|
||||
const tNode = getCurrentTNode()!;
|
||||
cancelLeavingNodes(tNode, lView);
|
||||
|
||||
allLeavingAnimations.add(lView);
|
||||
|
||||
addAnimationToLView(getLViewLeaveAnimations(lView), tNode, () =>
|
||||
|
||||
@@ -12,10 +12,12 @@ import {
|
||||
AfterViewInit,
|
||||
AnimationCallbackEvent,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
computed,
|
||||
Directive,
|
||||
ElementRef,
|
||||
inject,
|
||||
NgModule,
|
||||
OnDestroy,
|
||||
provideZonelessChangeDetection,
|
||||
@@ -1627,6 +1629,55 @@ describe('Animation', () => {
|
||||
expect(paragraphs.length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should reset leave animation and not duplicate node when toggled programmatically very quickly', fakeAsync(() => {
|
||||
const animateStyles = `
|
||||
.fade {
|
||||
animation: fade-out 500ms;
|
||||
}
|
||||
@keyframes fade-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@Component({
|
||||
selector: 'test-cmp',
|
||||
styles: animateStyles,
|
||||
template: '<div>@if (show()) {<p animate.leave="fade">I should fade</p>}</div>',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class TestComponent {
|
||||
show = signal(false);
|
||||
cdr = inject(ChangeDetectorRef);
|
||||
|
||||
toggle() {
|
||||
this.show.update((s) => !s);
|
||||
setTimeout(() => {
|
||||
this.show.update((s) => !s);
|
||||
this.cdr.detectChanges();
|
||||
|
||||
setTimeout(() => {
|
||||
this.show.update((s) => !s);
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
TestBed.configureTestingModule({animationsEnabled: true});
|
||||
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const cmp = fixture.componentInstance;
|
||||
cmp.toggle();
|
||||
fixture.detectChanges();
|
||||
tickAnimationFrames(1);
|
||||
const paragraphs = fixture.debugElement.queryAll(By.css('p'));
|
||||
expect(paragraphs.length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should always run animations for `@for` loops when adding and removing quickly', fakeAsync(() => {
|
||||
const animateStyles = `
|
||||
.slide-in {
|
||||
|
||||
Reference in New Issue
Block a user