Skip to content

Commit 9139fe0

Browse files
thePunderWomanAndrewKushnir
authored andcommitted
fix(core): Fixes animate.leave binding to a string with spaces (#63366)
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
1 parent 4dec06d commit 9139fe0

File tree

2 files changed

+116
-4
lines changed

2 files changed

+116
-4
lines changed

packages/core/src/render3/instructions/animation.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,11 @@ function getClassList(value: Set<string> | null, resolvers: Function[] | undefin
430430
const classList = new Set<string>(value);
431431
if (resolvers && resolvers.length) {
432432
for (const resolverFn of resolvers) {
433-
const resolvedValue = resolverFn();
434-
if (resolvedValue instanceof Array) {
433+
const resolvedValue = getClassListFromValue(resolverFn);
434+
if (resolvedValue) {
435435
for (const rv of resolvedValue) {
436436
classList.add(rv);
437437
}
438-
} else {
439-
classList.add(resolvedValue);
440438
}
441439
}
442440
}

packages/core/test/acceptance/animation_spec.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,66 @@ describe('Animation', () => {
185185
expect(fixture.nativeElement.outerHTML).not.toContain('class="slide-out fade"');
186186
}));
187187

188+
it('should support binding strings with spaces', fakeAsync(() => {
189+
const multiple = `
190+
.slide-out {
191+
animation: slide-out 2ms;
192+
}
193+
.fade {
194+
animation: fade-out 1ms;
195+
}
196+
@keyframes slide-out {
197+
from {
198+
transform: translateX(0);
199+
}
200+
to {
201+
transform: translateX(10px);
202+
}
203+
}
204+
@keyframes fade-out {
205+
from {
206+
opacity: 1;
207+
}
208+
to {
209+
opacity: 0;
210+
}
211+
}
212+
`;
213+
@Component({
214+
selector: 'test-cmp',
215+
styles: multiple,
216+
template: `<div>@if (show()) {<p [animate.leave]="'slide-out fade'" #el>I should slide out</p>}</div>`,
217+
encapsulation: ViewEncapsulation.None,
218+
})
219+
class TestComponent {
220+
show = signal(true);
221+
@ViewChild('el', {read: ElementRef}) el!: ElementRef<HTMLParagraphElement>;
222+
}
223+
224+
TestBed.configureTestingModule({animationsEnabled: true});
225+
226+
const fixture = TestBed.createComponent(TestComponent);
227+
const cmp = fixture.componentInstance;
228+
fixture.detectChanges();
229+
const paragragh = fixture.debugElement.query(By.css('p'));
230+
231+
expect(fixture.nativeElement.outerHTML).not.toContain('class="slide-out fade"');
232+
cmp.show.set(false);
233+
fixture.detectChanges();
234+
tickAnimationFrames(1);
235+
expect(cmp.show()).toBeFalsy();
236+
fixture.detectChanges();
237+
expect(fixture.nativeElement.outerHTML).toContain('class="slide-out fade"');
238+
fixture.detectChanges();
239+
paragragh.nativeElement.dispatchEvent(
240+
new AnimationEvent('animationend', {animationName: 'fade-out'}),
241+
);
242+
paragragh.nativeElement.dispatchEvent(
243+
new AnimationEvent('animationend', {animationName: 'slide-out'}),
244+
);
245+
expect(fixture.nativeElement.outerHTML).not.toContain('class="slide-out fade"');
246+
}));
247+
188248
it('should support multiple classes as a single string with spaces', fakeAsync(() => {
189249
const multiple = `
190250
.slide-out {
@@ -812,6 +872,60 @@ describe('Animation', () => {
812872
expect(cmp.el.nativeElement.outerHTML).not.toContain('class="slide-in fade-in"');
813873
}));
814874

875+
it('should support binding to a string with a space', fakeAsync(() => {
876+
const multiple = `
877+
.slide-in {
878+
animation: slide-in 1ms;
879+
}
880+
.fade-in {
881+
animation: fade-in 2ms;
882+
}
883+
@keyframes slide-in {
884+
from {
885+
transform: translateX(-10px);
886+
}
887+
to {
888+
transform: translateX(0);
889+
}
890+
}
891+
@keyframes fade-in {
892+
from {
893+
opacity: 0;
894+
}
895+
to {
896+
opacity: 1;
897+
}
898+
}
899+
`;
900+
@Component({
901+
selector: 'test-cmp',
902+
styles: multiple,
903+
template: `<div>@if (show()) {<p [animate.enter]="'slide-in fade-in'" #el>I should slide in</p>}</div>`,
904+
encapsulation: ViewEncapsulation.None,
905+
})
906+
class TestComponent {
907+
show = signal(false);
908+
@ViewChild('el', {read: ElementRef}) el!: ElementRef<HTMLParagraphElement>;
909+
}
910+
TestBed.configureTestingModule({animationsEnabled: true});
911+
912+
const fixture = TestBed.createComponent(TestComponent);
913+
const cmp = fixture.componentInstance;
914+
fixture.detectChanges();
915+
expect(cmp.show()).toBeFalsy();
916+
cmp.show.set(true);
917+
fixture.detectChanges();
918+
tickAnimationFrames(1);
919+
const paragraph = fixture.debugElement.query(By.css('p'));
920+
expect(cmp.show()).toBeTruthy();
921+
expect(cmp.el.nativeElement.outerHTML).toContain('class="slide-in fade-in"');
922+
paragraph.nativeElement.dispatchEvent(new AnimationEvent('animationstart'));
923+
paragraph.nativeElement.dispatchEvent(
924+
new AnimationEvent('animationend', {animationName: 'fade-in'}),
925+
);
926+
expect(cmp.el.nativeElement.outerHTML).not.toContain('class="slide-in fade-in"');
927+
}));
928+
815929
it('should support multple classes as a single string separated by a space', fakeAsync(() => {
816930
const multiple = `
817931
.slide-in {

0 commit comments

Comments
 (0)