Skip to content

Commit 36ff785

Browse files
crisbetommalerba
authored andcommitted
fix(cdk-dialog): afterClosed event emitting twice on close (#11407)
* Fixes the `afterClosed` event from the CDK dialog emitting twice due to the `_animationDone` callback being invoked both with `void` and `exit` consecutively. * Fixes incorrect spelling of "Bulbasaur". Fixes #11398.
1 parent 64f2963 commit 36ff785

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

src/cdk-experimental/dialog/dialog-container.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
149149
if (event.toState === 'enter') {
150150
this._beforeEnter.next();
151151
}
152-
if (event.toState === 'void' || event.toState === 'exit') {
152+
if (event.fromState === 'enter' && (event.toState === 'void' || event.toState === 'exit')) {
153153
this._beforeExit.next();
154154
}
155155
}
@@ -160,7 +160,8 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
160160
this._autoFocusFirstTabbableElement();
161161
this._afterEnter.next();
162162
}
163-
if (event.toState === 'void' || event.toState === 'exit') {
163+
164+
if (event.fromState === 'enter' && (event.toState === 'void' || event.toState === 'exit')) {
164165
this._returnFocusAfterDialog();
165166
this._afterExit.next();
166167
}

src/cdk-experimental/dialog/dialog.spec.ts

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ describe('Dialog', () => {
170170
let dialogRef = dialog.openFromComponent(PizzaMsg, { viewContainerRef: testViewContainerRef });
171171
let afterCloseCallback = jasmine.createSpy('afterClose callback');
172172

173+
viewContainerFixture.detectChanges();
173174
dialogRef.afterClosed().subscribe(afterCloseCallback);
174175
dialogRef.close('Charmander');
175176
viewContainerFixture.detectChanges();
@@ -179,8 +180,22 @@ describe('Dialog', () => {
179180
expect(overlayContainerElement.querySelector('cdk-dialog-container')).toBeNull();
180181
}));
181182

183+
it('should only emit the afterCloseEvent once when closed', fakeAsync(() => {
184+
let dialogRef = dialog.openFromComponent(PizzaMsg, { viewContainerRef: testViewContainerRef });
185+
let afterCloseCallback = jasmine.createSpy('afterClose callback');
186+
187+
viewContainerFixture.detectChanges();
188+
dialogRef.afterClosed().subscribe(afterCloseCallback);
189+
dialogRef.close();
190+
viewContainerFixture.detectChanges();
191+
flush();
192+
193+
expect(afterCloseCallback).toHaveBeenCalledTimes(1);
194+
}));
195+
182196
it('should close a dialog and get back a result before it is closed', fakeAsync(() => {
183197
const dialogRef = dialog.openFromComponent(PizzaMsg, {viewContainerRef: testViewContainerRef});
198+
viewContainerFixture.detectChanges();
184199

185200
// beforeClose should emit before dialog container is destroyed
186201
const beforeCloseHandler = jasmine.createSpy('beforeClose callback').and.callFake(() => {
@@ -189,19 +204,18 @@ describe('Dialog', () => {
189204
});
190205

191206
dialogRef.beforeClose().subscribe(beforeCloseHandler);
192-
dialogRef.close('Bulbasaurus');
207+
dialogRef.close('Bulbasaur');
193208
viewContainerFixture.detectChanges();
194209
flush();
195210

196-
expect(beforeCloseHandler).toHaveBeenCalledWith('Bulbasaurus');
211+
expect(beforeCloseHandler).toHaveBeenCalledWith('Bulbasaur');
197212
expect(overlayContainerElement.querySelector('cdk-dialog-container')).toBeNull();
198213
}));
199214

200215
it('should close a dialog via the escape key', fakeAsync(() => {
201-
dialog.openFromComponent(PizzaMsg, {
202-
viewContainerRef: testViewContainerRef
203-
});
216+
dialog.openFromComponent(PizzaMsg, {viewContainerRef: testViewContainerRef});
204217

218+
viewContainerFixture.detectChanges();
205219
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
206220
viewContainerFixture.detectChanges();
207221
flush();
@@ -235,13 +249,10 @@ describe('Dialog', () => {
235249
}));
236250

237251
it('should close when clicking on the overlay backdrop', fakeAsync(() => {
238-
dialog.openFromComponent(PizzaMsg, {
239-
viewContainerRef: testViewContainerRef
240-
});
241-
252+
dialog.openFromComponent(PizzaMsg, {viewContainerRef: testViewContainerRef});
242253
viewContainerFixture.detectChanges();
243254

244-
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
255+
const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
245256

246257
backdrop.click();
247258
viewContainerFixture.detectChanges();
@@ -251,16 +262,12 @@ describe('Dialog', () => {
251262
}));
252263

253264
it('should emit the backdropClick stream when clicking on the overlay backdrop', fakeAsync(() => {
254-
const dialogRef = dialog.openFromComponent(PizzaMsg, {
255-
viewContainerRef: testViewContainerRef
256-
});
257-
265+
const dialogRef = dialog.openFromComponent(PizzaMsg, {viewContainerRef: testViewContainerRef});
258266
const spy = jasmine.createSpy('backdropClick spy');
259267
dialogRef.backdropClick().subscribe(spy);
260-
261268
viewContainerFixture.detectChanges();
262269

263-
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
270+
const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
264271

265272
backdrop.click();
266273
expect(spy).toHaveBeenCalledTimes(1);
@@ -304,7 +311,7 @@ describe('Dialog', () => {
304311
ContentElementDialog, { viewContainerRef: testViewContainerRef });
305312
const spy = jasmine.createSpy('afterAllClosed spy');
306313

307-
314+
viewContainerFixture.detectChanges();
308315
dialog.afterAllClosed.subscribe(spy);
309316

310317
ref1.close();
@@ -532,8 +539,11 @@ describe('Dialog', () => {
532539

533540
it('should close all of the dialogs', fakeAsync(() => {
534541
dialog.openFromComponent(PizzaMsg);
542+
viewContainerFixture.detectChanges();
535543
dialog.openFromComponent(PizzaMsg);
544+
viewContainerFixture.detectChanges();
536545
dialog.openFromComponent(PizzaMsg);
546+
viewContainerFixture.detectChanges();
537547

538548
expect(overlayContainerElement.querySelectorAll('cdk-dialog-container').length).toBe(3);
539549

@@ -558,7 +568,9 @@ describe('Dialog', () => {
558568

559569
it('should close all dialogs when the user goes forwards/backwards in history', fakeAsync(() => {
560570
dialog.openFromComponent(PizzaMsg);
571+
viewContainerFixture.detectChanges();
561572
dialog.openFromComponent(PizzaMsg);
573+
viewContainerFixture.detectChanges();
562574

563575
expect(overlayContainerElement.querySelectorAll('cdk-dialog-container').length).toBe(2);
564576

@@ -571,7 +583,9 @@ describe('Dialog', () => {
571583

572584
it('should close all open dialogs when the location hash changes', fakeAsync(() => {
573585
dialog.openFromComponent(PizzaMsg);
586+
viewContainerFixture.detectChanges();
574587
dialog.openFromComponent(PizzaMsg);
588+
viewContainerFixture.detectChanges();
575589

576590
expect(overlayContainerElement.querySelectorAll('cdk-dialog-container').length).toBe(2);
577591

@@ -622,13 +636,15 @@ describe('Dialog', () => {
622636
it('should default to null if no data is passed', () => {
623637
expect(() => {
624638
let dialogRef = dialog.openFromComponent(DialogWithInjectedData);
639+
viewContainerFixture.detectChanges();
625640
expect(dialogRef.componentInstance.data).toBeNull();
626641
}).not.toThrow();
627642
});
628643
});
629644

630645
it('should not keep a reference to the component after the dialog is closed', fakeAsync(() => {
631646
let dialogRef = dialog.openFromComponent(PizzaMsg);
647+
viewContainerFixture.detectChanges();
632648

633649
expect(dialogRef.componentInstance).toBeTruthy();
634650

@@ -977,6 +993,7 @@ describe('Dialog with a parent Dialog', () => {
977993

978994
it('should close the top dialog via the escape key', fakeAsync(() => {
979995
childDialog.openFromComponent(PizzaMsg);
996+
fixture.detectChanges();
980997

981998
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
982999
fixture.detectChanges();

0 commit comments

Comments
 (0)