Skip to content

Commit 81a73c6

Browse files
macjohnnyjosephperrott
authored andcommitted
fix(select): Fixes width-issue of select option panel in IE (#11801)
* fix(select): Fixes width-issue of select option panel in IE11 Fixes the select options panel width not matching the select width in IE11 Fixes #11609 * code cleanup * fix leave-animation of select panel not working due to angular/angular#23302
1 parent 3c5e671 commit 81a73c6

File tree

8 files changed

+70
-12
lines changed

8 files changed

+70
-12
lines changed

src/dev-app/select/select-demo.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ <h4>Error message with errorStateMatcher</h4>
168168
<mat-card>
169169
<mat-card-subtitle>ngModel</mat-card-subtitle>
170170

171-
<mat-form-field [floatLabel]="floatLabel" [color]="drinksTheme">
171+
<mat-form-field [floatLabel]="floatLabel" [color]="drinksTheme"
172+
[class.demo-drinks-width-large]="drinksWidth === '400px'">
172173
<mat-label>Drink</mat-label>
173174
<mat-select [(ngModel)]="currentDrink" [required]="drinksRequired"
174175
[disabled]="drinksDisabled" #drinkControl="ngModel">
@@ -193,6 +194,13 @@ <h4>Error message with errorStateMatcher</h4>
193194
<option value="never">Never</option>
194195
</select>
195196
</p>
197+
<p>
198+
<label for="drinks-width">Width:</label>
199+
<select [(ngModel)]="drinksWidth" id="drinks-width">
200+
<option value="default">Default</option>
201+
<option value="400px">400px</option>
202+
</select>
203+
</p>
196204
<p>
197205
<label for="drinks-theme">Theme:</label>
198206
<select [(ngModel)]="drinksTheme" id="drinks-theme">

src/dev-app/select/select-demo.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
vertical-align: bottom;
1212
padding-right: 0.25em;
1313
}
14+
15+
.demo-drinks-width-large {
16+
width: 400px;
17+
}
1418
}
1519

1620
.demo-card {

src/dev-app/select/select-demo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class SelectDemo {
4141
currentAppearanceValue: string | null;
4242
latestChangeEvent: MatSelectChange;
4343
floatLabel = 'auto';
44+
drinksWidth = 'default';
4445
foodControl = new FormControl('pizza-1');
4546
topHeightCtrl = new FormControl(0);
4647
drinksTheme = 'primary';

src/lib/select/select-animations.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
import {
1010
animate,
11+
animateChild,
1112
AnimationTriggerMetadata,
13+
query,
1214
state,
1315
style,
1416
transition,
@@ -23,9 +25,20 @@ import {
2325
* @docs-private
2426
*/
2527
export const matSelectAnimations: {
28+
readonly transformPanelWrap: AnimationTriggerMetadata;
2629
readonly transformPanel: AnimationTriggerMetadata;
2730
readonly fadeInContent: AnimationTriggerMetadata;
2831
} = {
32+
/**
33+
* This animation ensures the select's overlay panel animation (transformPanel) is called when
34+
* closing the select.
35+
* This is needed due to https://github.com/angular/angular/issues/23302
36+
*/
37+
transformPanelWrap: trigger('transformPanelWrap', [
38+
transition('* => void', query('@transformPanel', [animateChild()],
39+
{optional: true}))
40+
]),
41+
2942
/**
3043
* This animation transforms the select's overlay panel on and off the page.
3144
*

src/lib/select/select.html

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,17 @@
2929
(backdropClick)="close()"
3030
(attach)="_onAttached()"
3131
(detach)="close()">
32-
33-
<div
34-
#panel
35-
class="mat-select-panel {{ _getPanelTheme() }}"
36-
[ngClass]="panelClass"
37-
[@transformPanel]="multiple ? 'showing-multiple' : 'showing'"
38-
(@transformPanel.done)="_panelDoneAnimatingStream.next($event.toState)"
39-
[style.transformOrigin]="_transformOrigin"
40-
[style.font-size.px]="_triggerFontSize"
41-
(keydown)="_handleKeydown($event)">
42-
<ng-content></ng-content>
32+
<div class="mat-select-panel-wrap" [@transformPanelWrap]>
33+
<div
34+
#panel
35+
class="mat-select-panel {{ _getPanelTheme() }}"
36+
[ngClass]="panelClass"
37+
[@transformPanel]="multiple ? 'showing-multiple' : 'showing'"
38+
(@transformPanel.done)="_panelDoneAnimatingStream.next($event.toState)"
39+
[style.transformOrigin]="_transformOrigin"
40+
[style.font-size.px]="_triggerFontSize"
41+
(keydown)="_handleKeydown($event)">
42+
<ng-content></ng-content>
43+
</div>
4344
</div>
4445
</ng-template>

src/lib/select/select.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ $mat-select-placeholder-arrow-space: 2 * ($mat-select-arrow-size + $mat-select-a
8383
margin: 0 $mat-select-arrow-margin;
8484
}
8585

86+
.mat-select-panel-wrap {
87+
// Prevents width-issues of mat-select-panel with width: calc(100% + 32px)
88+
// in IE11 due to the parents display: flex;
89+
flex-basis: 100%;
90+
}
91+
8692
.mat-select-panel {
8793
@include mat-menu-base();
8894
padding-top: 0;

src/lib/select/select.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,29 @@ describe('MatSelect', () => {
10041004

10051005
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
10061006
expect(pane.style.minWidth).toBe('200px');
1007+
1008+
const scrollContainer = document.querySelector('.cdk-overlay-pane .mat-select-panel');
1009+
const scrollContainerWidth = scrollContainer!.getBoundingClientRect().width;
1010+
expect(scrollContainerWidth).toBeCloseTo(200 + 32, 0,
1011+
'Expected select panel width to be 100% + 32px of the select field trigger');
1012+
}));
1013+
1014+
it('should set the width of the overlay based on a larger trigger width',
1015+
fakeAsync(() => {
1016+
// the trigger width exceeds the minimum width of the mat-select-panel
1017+
trigger.style.width = '400px';
1018+
1019+
trigger.click();
1020+
fixture.detectChanges();
1021+
flush();
1022+
1023+
const pane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;
1024+
expect(pane.style.minWidth).toBe('400px');
1025+
1026+
const scrollContainer = document.querySelector('.cdk-overlay-pane .mat-select-panel');
1027+
const scrollContainerWidth = scrollContainer!.getBoundingClientRect().width;
1028+
expect(scrollContainerWidth).toBeCloseTo(400 + 32, 0,
1029+
'Expected select panel width to be 100% + 32px of the select field trigger');
10071030
}));
10081031

10091032
it('should not attempt to open a select that does not have any options', fakeAsync(() => {
@@ -3110,6 +3133,7 @@ describe('MatSelect', () => {
31103133

31113134
checkTriggerAlignedWithOption(7, groupFixture.componentInstance.select);
31123135
}));
3136+
31133137
});
31143138

31153139
describe('limited space to open vertically', () => {

src/lib/select/select.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export class MatSelectTrigger {}
216216
'(blur)': '_onBlur()',
217217
},
218218
animations: [
219+
matSelectAnimations.transformPanelWrap,
219220
matSelectAnimations.transformPanel
220221
],
221222
providers: [

0 commit comments

Comments
 (0)