Skip to content

Commit f38bcd9

Browse files
timmoyjelbourn
authored andcommitted
feat(select): add option to disable option-based alignment (#9885)
1 parent aed7e8a commit f38bcd9

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/lib/select/select.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,6 +2704,41 @@ describe('MatSelect', () => {
27042704

27052705
});
27062706

2707+
describe('with option centering disabled', () => {
2708+
beforeEach(async(() => configureMatSelectTestingModule([
2709+
SelectWithoutOptionCentering,
2710+
])));
2711+
2712+
let fixture: ComponentFixture<SelectWithoutOptionCentering>;
2713+
let trigger: HTMLElement;
2714+
let select: HTMLElement;
2715+
let formField: HTMLElement;
2716+
2717+
beforeEach(fakeAsync(() => {
2718+
fixture = TestBed.createComponent(SelectWithoutOptionCentering);
2719+
fixture.detectChanges();
2720+
trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
2721+
select = fixture.debugElement.query(By.css('mat-select')).nativeElement;
2722+
formField = fixture.debugElement.query(By.css('mat-form-field')).nativeElement;
2723+
}));
2724+
2725+
it('should not align the active option with the trigger if centering is disabled',
2726+
fakeAsync(() => {
2727+
trigger.click();
2728+
fixture.detectChanges();
2729+
flush();
2730+
2731+
const scrollContainer = document.querySelector('.cdk-overlay-pane .mat-select-panel')!;
2732+
2733+
// The panel should be scrolled to 0 because centering the option disabled.
2734+
expect(scrollContainer.scrollTop).toEqual(0, `Expected panel not to be scrolled.`);
2735+
// The trigger should contain 'Pizza' because it was preselected
2736+
expect(trigger.textContent).toContain('Pizza');
2737+
// The selected index should be 1 because it was preselected
2738+
expect(fixture.componentInstance.options.toArray()[1].selected).toBe(true);
2739+
}));
2740+
});
2741+
27072742
describe('positioning', () => {
27082743
beforeEach(async(() => configureMatSelectTestingModule([
27092744
BasicSelect,
@@ -4445,3 +4480,32 @@ class SingleSelectWithPreselectedArrayValues {
44454480
@ViewChild(MatSelect) select: MatSelect;
44464481
@ViewChildren(MatOption) options: QueryList<MatOption>;
44474482
}
4483+
4484+
@Component({
4485+
selector: 'select-without-option-centering',
4486+
template: `
4487+
<mat-form-field>
4488+
<mat-select placeholder="Food" [formControl]="control" disableOptionCentering>
4489+
<mat-option *ngFor="let food of foods" [value]="food.value">
4490+
{{ food.viewValue }}
4491+
</mat-option>
4492+
</mat-select>
4493+
</mat-form-field>
4494+
`
4495+
})
4496+
class SelectWithoutOptionCentering {
4497+
foods: any[] = [
4498+
{ value: 'steak-0', viewValue: 'Steak' },
4499+
{ value: 'pizza-1', viewValue: 'Pizza' },
4500+
{ value: 'tacos-2', viewValue: 'Tacos'},
4501+
{ value: 'sandwich-3', viewValue: 'Sandwich' },
4502+
{ value: 'chips-4', viewValue: 'Chips' },
4503+
{ value: 'eggs-5', viewValue: 'Eggs' },
4504+
{ value: 'pasta-6', viewValue: 'Pasta' },
4505+
{ value: 'sushi-7', viewValue: 'Sushi' },
4506+
];
4507+
control = new FormControl('pizza-1');
4508+
4509+
@ViewChild(MatSelect) select: MatSelect;
4510+
@ViewChildren(MatOption) options: QueryList<MatOption>;
4511+
}

src/lib/select/select.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
308308
},
309309
];
310310

311+
/** Whether the component is disabling centering of the active option over the trigger. */
312+
private _disableOptionCentering: boolean = false;
313+
311314
/** Whether the select is focused. */
312315
focused: boolean = false;
313316

@@ -362,6 +365,13 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
362365
this._multiple = coerceBooleanProperty(value);
363366
}
364367

368+
/** Whether to center the active option over the trigger. */
369+
@Input()
370+
get disableOptionCentering(): boolean { return this._disableOptionCentering; }
371+
set disableOptionCentering(value: boolean) {
372+
this._disableOptionCentering = coerceBooleanProperty(value);
373+
}
374+
365375
/**
366376
* A function to compare the option values with the selected values. The first argument
367377
* is a value from an option. The second is a value from the selection. A boolean
@@ -1118,6 +1128,11 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
11181128
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
11191129
let optionOffsetFromPanelTop: number;
11201130

1131+
// Disable offset if requested by user by returning 0 as value to offset
1132+
if (this._disableOptionCentering) {
1133+
return 0;
1134+
}
1135+
11211136
if (this._scrollTop === 0) {
11221137
optionOffsetFromPanelTop = selectedIndex * itemHeight;
11231138
} else if (this._scrollTop === maxScroll) {

0 commit comments

Comments
 (0)