Skip to content

Commit b3458a7

Browse files
crisbetojosephperrott
authored andcommitted
fix(drawer): re-add openedStart and closedStart events
* Re-adds the `openedStart` and `closedStart` events due to popular demand. * Fixes wrong signature for the returned promise from toggle. The signature states that the resolved value is supposed to be a `MatDrawerToggleResult` while in practice it was `undefined`. * Splits out a long unit test into two smaller ones. Fixes #6924.
1 parent dfe8091 commit b3458a7

File tree

3 files changed

+108
-18
lines changed

3 files changed

+108
-18
lines changed

src/demo-app/drawer/drawer-demo.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h2>Basic Use Case</h2>
22

33
<mat-drawer-container class="demo-drawer-container">
4-
<mat-drawer #start (open)="myinput.focus()" mode="side">
4+
<mat-drawer #start (opened)="myinput.focus()" mode="side">
55
Start Side Drawer
66
<br>
77
<button mat-button (click)="start.close()">Close</button>

src/lib/sidenav/drawer.spec.ts

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,98 @@ describe('MatDrawer', () => {
2828
}));
2929

3030
describe('methods', () => {
31-
it('should be able to open and close', fakeAsync(() => {
32-
let fixture = TestBed.createComponent(BasicTestApp);
31+
it('should be able to open', fakeAsync(() => {
32+
const fixture = TestBed.createComponent(BasicTestApp);
3333

3434
fixture.detectChanges();
3535

36-
let testComponent: BasicTestApp = fixture.debugElement.componentInstance;
37-
let drawer = fixture.debugElement.query(By.directive(MatDrawer));
38-
let drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));
36+
const testComponent: BasicTestApp = fixture.debugElement.componentInstance;
37+
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
38+
const drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));
3939

4040
drawerBackdropElement.nativeElement.style.transition = 'none';
4141
fixture.debugElement.query(By.css('.open')).nativeElement.click();
4242
fixture.detectChanges();
4343

4444
expect(testComponent.openCount).toBe(0);
45-
expect(testComponent.closeCount).toBe(0);
45+
expect(testComponent.openStartCount).toBe(0);
4646

4747
tick();
48+
expect(testComponent.openStartCount).toBe(1);
4849
fixture.detectChanges();
4950

5051
expect(testComponent.openCount).toBe(1);
51-
expect(testComponent.closeCount).toBe(0);
52+
expect(testComponent.openStartCount).toBe(1);
5253
expect(getComputedStyle(drawer.nativeElement).visibility).toBe('visible');
5354
expect(getComputedStyle(drawerBackdropElement.nativeElement).visibility).toBe('visible');
55+
}));
56+
57+
it('should be able to close', fakeAsync(() => {
58+
const fixture = TestBed.createComponent(BasicTestApp);
59+
60+
fixture.detectChanges();
61+
62+
const testComponent: BasicTestApp = fixture.debugElement.componentInstance;
63+
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
64+
const drawerBackdropElement = fixture.debugElement.query(By.css('.mat-drawer-backdrop'));
65+
66+
drawerBackdropElement.nativeElement.style.transition = 'none';
67+
fixture.debugElement.query(By.css('.open')).nativeElement.click();
68+
fixture.detectChanges();
69+
tick();
70+
fixture.detectChanges();
5471

5572
fixture.debugElement.query(By.css('.close')).nativeElement.click();
5673
fixture.detectChanges();
5774

58-
expect(testComponent.openCount).toBe(1);
5975
expect(testComponent.closeCount).toBe(0);
76+
expect(testComponent.closeStartCount).toBe(0);
6077

6178
tick();
79+
expect(testComponent.closeStartCount).toBe(1);
6280
fixture.detectChanges();
6381

64-
expect(testComponent.openCount).toBe(1);
6582
expect(testComponent.closeCount).toBe(1);
83+
expect(testComponent.closeStartCount).toBe(1);
6684
expect(getComputedStyle(drawer.nativeElement).visibility).toBe('hidden');
6785
expect(getComputedStyle(drawerBackdropElement.nativeElement).visibility).toBe('hidden');
6886
}));
6987

88+
it('should resolve the open method promise with an object', fakeAsync(() => {
89+
const fixture = TestBed.createComponent(BasicTestApp);
90+
fixture.detectChanges();
91+
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
92+
93+
drawer.componentInstance.open().then(result => {
94+
expect(result).toBeTruthy();
95+
expect(result.type).toBe('open');
96+
expect(result.animationFinished).toBe(true);
97+
});
98+
fixture.detectChanges();
99+
tick();
100+
fixture.detectChanges();
101+
}));
102+
103+
it('should resolve the close method promise with an object', fakeAsync(() => {
104+
const fixture = TestBed.createComponent(BasicTestApp);
105+
fixture.detectChanges();
106+
const drawer = fixture.debugElement.query(By.directive(MatDrawer));
107+
108+
drawer.componentInstance.open();
109+
fixture.detectChanges();
110+
tick();
111+
fixture.detectChanges();
112+
113+
drawer.componentInstance.close().then(result => {
114+
expect(result).toBeTruthy();
115+
expect(result.type).toBe('close');
116+
expect(result.animationFinished).toBe(true);
117+
});
118+
fixture.detectChanges();
119+
tick();
120+
fixture.detectChanges();
121+
}));
122+
70123
it('should be able to close while the open animation is running', fakeAsync(() => {
71124
const fixture = TestBed.createComponent(BasicTestApp);
72125
fixture.detectChanges();
@@ -139,13 +192,16 @@ describe('MatDrawer', () => {
139192
tick();
140193

141194
expect(testComponent.openCount).toBe(1, 'Expected one open event.');
195+
expect(testComponent.openStartCount).toBe(1, 'Expected one open start event.');
142196
expect(testComponent.closeCount).toBe(0, 'Expected no close events.');
197+
expect(testComponent.closeStartCount).toBe(0, 'Expected no close start events.');
143198

144199
dispatchKeyboardEvent(drawer.nativeElement, 'keydown', ESCAPE);
145200
fixture.detectChanges();
146201
tick();
147202

148203
expect(testComponent.closeCount).toBe(1, 'Expected one close event.');
204+
expect(testComponent.closeStartCount).toBe(1, 'Expected one close start event.');
149205
}));
150206

151207
it('should fire the open event when open on init', fakeAsync(() => {
@@ -172,6 +228,7 @@ describe('MatDrawer', () => {
172228
tick();
173229

174230
expect(testComponent.closeCount).toBe(0);
231+
expect(testComponent.closeStartCount).toBe(0);
175232
}));
176233

177234
it('should not close by clicking on the backdrop when disableClose is set', fakeAsync(() => {
@@ -189,6 +246,7 @@ describe('MatDrawer', () => {
189246
tick();
190247

191248
expect(testComponent.closeCount).toBe(0);
249+
expect(testComponent.closeStartCount).toBe(0);
192250
}));
193251

194252
it('should restore focus on close if focus is inside drawer', fakeAsync(() => {
@@ -490,17 +548,21 @@ class DrawerContainerTwoDrawerTestApp {
490548
<mat-drawer-container (backdropClick)="backdropClicked()">
491549
<mat-drawer #drawer position="start"
492550
(opened)="open()"
493-
(closed)="close()">
551+
(openedStart)="openStart()"
552+
(closed)="close()"
553+
(closedStart)="closeStart()">
494554
<button #drawerButton>Content.</button>
495555
</mat-drawer>
496556
<button (click)="drawer.open()" class="open" #openButton></button>
497557
<button (click)="drawer.close()" class="close" #closeButton></button>
498558
</mat-drawer-container>`,
499559
})
500560
class BasicTestApp {
501-
openCount: number = 0;
502-
closeCount: number = 0;
503-
backdropClickedCount: number = 0;
561+
openCount = 0;
562+
openStartCount = 0;
563+
closeCount = 0;
564+
closeStartCount = 0;
565+
backdropClickedCount = 0;
504566

505567
@ViewChild('drawerButton') drawerButton: ElementRef;
506568
@ViewChild('openButton') openButton: ElementRef;
@@ -510,10 +572,18 @@ class BasicTestApp {
510572
this.openCount++;
511573
}
512574

575+
openStart() {
576+
this.openStartCount++;
577+
}
578+
513579
close() {
514580
this.closeCount++;
515581
}
516582

583+
closeStart() {
584+
this.closeStartCount++;
585+
}
586+
517587
backdropClicked() {
518588
this.backdropClickedCount++;
519589
}

src/lib/sidenav/drawer.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,39 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
193193
return this.openedChange.pipe(filter(o => o), map(() => {}));
194194
}
195195

196+
/** Event emitted when the drawer has started opening. */
197+
@Output()
198+
get openedStart(): Observable<void> {
199+
return this._animationStarted.pipe(
200+
filter(e => e.fromState !== e.toState && e.toState.indexOf('open') === 0),
201+
map(() => {})
202+
);
203+
}
204+
196205
/** Event emitted when the drawer has been closed. */
197206
@Output('closed')
198207
get _closedStream(): Observable<void> {
199208
return this.openedChange.pipe(filter(o => !o), map(() => {}));
200209
}
201210

211+
/** Event emitted when the drawer has started closing. */
212+
@Output()
213+
get closedStart(): Observable<void> {
214+
return this._animationStarted.pipe(
215+
filter(e => e.fromState !== e.toState && e.toState === 'void'),
216+
map(() => {})
217+
);
218+
}
219+
202220
/**
203221
* Event emitted when the drawer is fully opened.
204-
* @deprecated Use `openedChange` instead.
222+
* @deprecated Use `opened` instead.
205223
*/
206224
@Output('open') onOpen = this._openedStream;
207225

208226
/**
209227
* Event emitted when the drawer is fully closed.
210-
* @deprecated Use `openedChange` instead.
228+
* @deprecated Use `closed` instead.
211229
*/
212230
@Output('close') onClose = this._closedStream;
213231

@@ -327,8 +345,10 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
327345

328346
// TODO(crisbeto): This promise is here for backwards-compatibility.
329347
// It should be removed next time we do breaking changes in the drawer.
330-
return new Promise(resolve => {
331-
(isOpen ? this.onOpen : this.onClose).pipe(first()).subscribe(resolve);
348+
return new Promise<any>(resolve => {
349+
this.openedChange.pipe(first()).subscribe(open => {
350+
resolve(new MatDrawerToggleResult(open ? 'open' : 'close', true));
351+
});
332352
});
333353
}
334354

0 commit comments

Comments
 (0)