Skip to content

Commit 17f7e82

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 angular#3639. Fixes angular#3244.
1 parent aa3360a commit 17f7e82

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
@@ -43,7 +43,9 @@ describe('MdSelect', () => {
4343
ThrowsErrorOnInit,
4444
BasicSelectOnPush,
4545
BasicSelectOnPushPreselected,
46-
SelectWithPlainTabindex
46+
SelectWithPlainTabindex,
47+
BasicSelectInitiallyHidden,
48+
BasicSelectNoPlaceholder
4749
],
4850
providers: [
4951
{provide: OverlayContainer, useFactory: () => {
@@ -155,6 +157,25 @@ describe('MdSelect', () => {
155157
});
156158
}));
157159

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

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

170206
describe('selection logic', () => {
@@ -1893,6 +1929,27 @@ class MultiSelect {
18931929
})
18941930
class SelectWithPlainTabindex { }
18951931

1932+
@Component({
1933+
selector: 'basic-select-initially-hidden',
1934+
template: `
1935+
<md-select [style.display]="isVisible ? 'block' : 'none'">
1936+
<md-option value="value">There are no other options</md-option>
1937+
</md-select>
1938+
`
1939+
})
1940+
class BasicSelectInitiallyHidden {
1941+
isVisible = false;
1942+
}
1943+
1944+
@Component({
1945+
selector: 'basic-select-no-placeholder',
1946+
template: `
1947+
<md-select>
1948+
<md-option value="value">There are no other options</md-option>
1949+
</md-select>
1950+
`
1951+
})
1952+
class BasicSelectNoPlaceholder { }
18961953

18971954
class FakeViewportRuler {
18981955
getViewportRect() {

src/lib/select/select.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
236236
this._placeholder = value;
237237

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

242242
/** Whether the component is disabled. */
@@ -341,6 +341,11 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
341341
if (this.disabled || !this.options.length) {
342342
return;
343343
}
344+
345+
if (!this._triggerWidth) {
346+
this._setTriggerWidth();
347+
}
348+
344349
this._calculateOverlayPosition();
345350
this._placeholderState = this._floatPlaceholderState();
346351
this._panelOpen = true;
@@ -423,11 +428,12 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
423428
return this._dir ? this._dir.value === 'rtl' : false;
424429
}
425430

426-
/** The width of the trigger element. This is necessary to match
431+
/**
432+
* Sets the width of the trigger element. This is necessary to match
427433
* the overlay width to the trigger width.
428434
*/
429-
_getWidth(): number {
430-
return this._getTriggerRect().width;
435+
private _setTriggerWidth(): void {
436+
this._triggerWidth = this._getTriggerRect().width;
431437
}
432438

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

0 commit comments

Comments
 (0)