Skip to content

Commit 055111c

Browse files
committed
fix(select): wrong panel width if element is hidden initially
Fixes the select not having a proper width if it became visible after it was initialized. Fixes #3639. Fixes #3244.
1 parent ab77fa9 commit 055111c

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed

src/lib/select/select.spec.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ describe('MdSelect', () => {
4747
BasicSelectOnPush,
4848
BasicSelectOnPushPreselected,
4949
SelectWithPlainTabindex,
50-
SelectEarlyAccessSibling
50+
SelectEarlyAccessSibling,
51+
BasicSelectInitiallyHidden,
52+
BasicSelectNoPlaceholder
5153
],
5254
providers: [
5355
{provide: OverlayContainer, useFactory: () => {
@@ -159,6 +161,25 @@ describe('MdSelect', () => {
159161
});
160162
}));
161163

164+
it('should set the width of the overlay if the element was hidden initially', async(() => {
165+
let initiallyHidden = TestBed.createComponent(BasicSelectInitiallyHidden);
166+
167+
initiallyHidden.detectChanges();
168+
trigger = initiallyHidden.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
169+
trigger.style.width = '200px';
170+
171+
initiallyHidden.componentInstance.isVisible = true;
172+
initiallyHidden.detectChanges();
173+
174+
initiallyHidden.whenStable().then(() => {
175+
trigger.click();
176+
initiallyHidden.detectChanges();
177+
178+
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
179+
expect(pane.style.minWidth).toBe('200px');
180+
});
181+
}));
182+
162183
it('should not attempt to open a select that does not have any options', () => {
163184
fixture.componentInstance.foods = [];
164185
fixture.detectChanges();
@@ -169,6 +190,21 @@ describe('MdSelect', () => {
169190
expect(fixture.componentInstance.select.panelOpen).toBe(false);
170191
});
171192

193+
it('should set the width of the overlay if there is no placeholder', async(() => {
194+
let noPlaceholder = TestBed.createComponent(BasicSelectNoPlaceholder);
195+
196+
noPlaceholder.detectChanges();
197+
trigger = noPlaceholder.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
198+
199+
noPlaceholder.whenStable().then(() => {
200+
trigger.click();
201+
noPlaceholder.detectChanges();
202+
203+
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
204+
expect(parseInt(pane.style.minWidth)).toBeGreaterThan(0);
205+
});
206+
}));
207+
172208
});
173209

174210
describe('selection logic', () => {
@@ -1957,6 +1993,27 @@ class SelectWithPlainTabindex { }
19571993
})
19581994
class SelectEarlyAccessSibling { }
19591995

1996+
@Component({
1997+
selector: 'basic-select-initially-hidden',
1998+
template: `
1999+
<md-select [style.display]="isVisible ? 'block' : 'none'">
2000+
<md-option value="value">There are no other options</md-option>
2001+
</md-select>
2002+
`
2003+
})
2004+
class BasicSelectInitiallyHidden {
2005+
isVisible = false;
2006+
}
2007+
2008+
@Component({
2009+
selector: 'basic-select-no-placeholder',
2010+
template: `
2011+
<md-select>
2012+
<md-option value="value">There are no other options</md-option>
2013+
</md-select>
2014+
`
2015+
})
2016+
class BasicSelectNoPlaceholder { }
19602017

19612018
class FakeViewportRuler {
19622019
getViewportRect() {

src/lib/select/select.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
238238
this._placeholder = value;
239239

240240
// Must wait to record the trigger width to ensure placeholder width is included.
241-
Promise.resolve(null).then(() => this._triggerWidth = this._getWidth());
241+
Promise.resolve(null).then(() => this._setTriggerWidth());
242242
}
243243

244244
/** Whether the component is disabled. */
@@ -352,6 +352,11 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
352352
if (this.disabled || !this.options.length) {
353353
return;
354354
}
355+
356+
if (!this._triggerWidth) {
357+
this._setTriggerWidth();
358+
}
359+
355360
this._calculateOverlayPosition();
356361
this._placeholderState = this._floatPlaceholderState();
357362
this._panelOpen = true;
@@ -443,11 +448,12 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
443448
return this._dir ? this._dir.value === 'rtl' : false;
444449
}
445450

446-
/** The width of the trigger element. This is necessary to match
451+
/**
452+
* Sets the width of the trigger element. This is necessary to match
447453
* the overlay width to the trigger width.
448454
*/
449-
_getWidth(): number {
450-
return this._getTriggerRect().width;
455+
private _setTriggerWidth(): void {
456+
this._triggerWidth = this._getTriggerRect().width;
451457
}
452458

453459
/** Ensures the panel opens if activated by the keyboard. */

0 commit comments

Comments
 (0)