feat(select): add option to disable option-based alignment (#9885)

This commit is contained in:
timmoy
2018-02-17 20:21:20 -05:00
committed by Jeremy Elbourn
parent aed7e8aa0a
commit f38bcd9292
2 changed files with 79 additions and 0 deletions
+64
View File
@@ -2704,6 +2704,41 @@ describe('MatSelect', () => {
});
describe('with option centering disabled', () => {
beforeEach(async(() => configureMatSelectTestingModule([
SelectWithoutOptionCentering,
])));
let fixture: ComponentFixture<SelectWithoutOptionCentering>;
let trigger: HTMLElement;
let select: HTMLElement;
let formField: HTMLElement;
beforeEach(fakeAsync(() => {
fixture = TestBed.createComponent(SelectWithoutOptionCentering);
fixture.detectChanges();
trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
select = fixture.debugElement.query(By.css('mat-select')).nativeElement;
formField = fixture.debugElement.query(By.css('mat-form-field')).nativeElement;
}));
it('should not align the active option with the trigger if centering is disabled',
fakeAsync(() => {
trigger.click();
fixture.detectChanges();
flush();
const scrollContainer = document.querySelector('.cdk-overlay-pane .mat-select-panel')!;
// The panel should be scrolled to 0 because centering the option disabled.
expect(scrollContainer.scrollTop).toEqual(0, `Expected panel not to be scrolled.`);
// The trigger should contain 'Pizza' because it was preselected
expect(trigger.textContent).toContain('Pizza');
// The selected index should be 1 because it was preselected
expect(fixture.componentInstance.options.toArray()[1].selected).toBe(true);
}));
});
describe('positioning', () => {
beforeEach(async(() => configureMatSelectTestingModule([
BasicSelect,
@@ -4445,3 +4480,32 @@ class SingleSelectWithPreselectedArrayValues {
@ViewChild(MatSelect) select: MatSelect;
@ViewChildren(MatOption) options: QueryList<MatOption>;
}
@Component({
selector: 'select-without-option-centering',
template: `
<mat-form-field>
<mat-select placeholder="Food" [formControl]="control" disableOptionCentering>
<mat-option *ngFor="let food of foods" [value]="food.value">
{{ food.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
`
})
class SelectWithoutOptionCentering {
foods: any[] = [
{ value: 'steak-0', viewValue: 'Steak' },
{ value: 'pizza-1', viewValue: 'Pizza' },
{ value: 'tacos-2', viewValue: 'Tacos'},
{ value: 'sandwich-3', viewValue: 'Sandwich' },
{ value: 'chips-4', viewValue: 'Chips' },
{ value: 'eggs-5', viewValue: 'Eggs' },
{ value: 'pasta-6', viewValue: 'Pasta' },
{ value: 'sushi-7', viewValue: 'Sushi' },
];
control = new FormControl('pizza-1');
@ViewChild(MatSelect) select: MatSelect;
@ViewChildren(MatOption) options: QueryList<MatOption>;
}
+15
View File
@@ -308,6 +308,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
},
];
/** Whether the component is disabling centering of the active option over the trigger. */
private _disableOptionCentering: boolean = false;
/** Whether the select is focused. */
focused: boolean = false;
@@ -362,6 +365,13 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
this._multiple = coerceBooleanProperty(value);
}
/** Whether to center the active option over the trigger. */
@Input()
get disableOptionCentering(): boolean { return this._disableOptionCentering; }
set disableOptionCentering(value: boolean) {
this._disableOptionCentering = coerceBooleanProperty(value);
}
/**
* A function to compare the option values with the selected values. The first argument
* 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,
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
let optionOffsetFromPanelTop: number;
// Disable offset if requested by user by returning 0 as value to offset
if (this._disableOptionCentering) {
return 0;
}
if (this._scrollTop === 0) {
optionOffsetFromPanelTop = selectedIndex * itemHeight;
} else if (this._scrollTop === maxScroll) {