Skip to content

Commit dbdc1a8

Browse files
crisbetommalerba
authored andcommitted
feat(select): add injection token for configuring default opti… (#17543)
Adds the `MAT_SELECT_CONFIG` injection token that consumers can use to customize the default options for the `mat-select` component. Fixes #17406.
1 parent bfdf323 commit dbdc1a8

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

src/material/select/select.spec.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
QueryList,
3030
ViewChild,
3131
ViewChildren,
32+
Provider,
3233
} from '@angular/core';
3334
import {
3435
async,
@@ -63,7 +64,7 @@ import {LiveAnnouncer} from '@angular/cdk/a11y';
6364
import {Subject, Subscription, EMPTY, Observable} from 'rxjs';
6465
import {map} from 'rxjs/operators';
6566
import {MatSelectModule} from './index';
66-
import {MatSelect} from './select';
67+
import {MatSelect, MAT_SELECT_CONFIG, MatSelectConfig} from './select';
6768
import {
6869
getMatSelectDynamicMultipleError,
6970
getMatSelectNonArrayValueError,
@@ -88,7 +89,7 @@ describe('MatSelect', () => {
8889
* overall test time.
8990
* @param declarations Components to declare for this block
9091
*/
91-
function configureMatSelectTestingModule(declarations: any[]) {
92+
function configureMatSelectTestingModule(declarations: any[], providers: Provider[] = []) {
9293
TestBed.configureTestingModule({
9394
imports: [
9495
MatFormFieldModule,
@@ -105,6 +106,7 @@ describe('MatSelect', () => {
105106
scrolled: () => scrolledSubject.asObservable(),
106107
}),
107108
},
109+
...providers
108110
],
109111
}).compileComponents();
110112

@@ -4447,6 +4449,22 @@ describe('MatSelect', () => {
44474449
}));
44484450

44494451
});
4452+
4453+
it('should be able to provide default values through an injection token', () => {
4454+
configureMatSelectTestingModule([NgModelSelect], [{
4455+
provide: MAT_SELECT_CONFIG,
4456+
useValue: {
4457+
disableOptionCentering: true,
4458+
typeaheadDebounceInterval: 1337
4459+
} as MatSelectConfig
4460+
}]);
4461+
const fixture = TestBed.createComponent(NgModelSelect);
4462+
fixture.detectChanges();
4463+
const select = fixture.componentInstance.select;
4464+
4465+
expect(select.disableOptionCentering).toBe(true);
4466+
expect(select.typeaheadDebounceInterval).toBe(1337);
4467+
});
44504468
});
44514469

44524470

src/material/select/select.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ export function MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay: Overlay):
151151
return () => overlay.scrollStrategies.reposition();
152152
}
153153

154+
/** Object that can be used to configure the default options for the select module. */
155+
export interface MatSelectConfig {
156+
/** Whether option centering should be disabled. */
157+
disableOptionCentering?: boolean;
158+
159+
/** Time to wait in milliseconds after the last keystroke before moving focus to an item. */
160+
typeaheadDebounceInterval?: number;
161+
}
162+
163+
/** Injection token that can be used to provide the default options the select module. */
164+
export const MAT_SELECT_CONFIG = new InjectionToken<MatSelectConfig>('MAT_SELECT_CONFIG');
165+
154166
/** @docs-private */
155167
export const MAT_SELECT_SCROLL_STRATEGY_PROVIDER = {
156168
provide: MAT_SELECT_SCROLL_STRATEGY,
@@ -507,7 +519,8 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
507519
@Self() @Optional() public ngControl: NgControl,
508520
@Attribute('tabindex') tabIndex: string,
509521
@Inject(MAT_SELECT_SCROLL_STRATEGY) scrollStrategyFactory: any,
510-
private _liveAnnouncer: LiveAnnouncer) {
522+
private _liveAnnouncer: LiveAnnouncer,
523+
@Optional() @Inject(MAT_SELECT_CONFIG) defaults?: MatSelectConfig) {
511524
super(elementRef, _defaultErrorStateMatcher, _parentForm,
512525
_parentFormGroup, ngControl);
513526

@@ -523,6 +536,16 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
523536

524537
// Force setter to be called in case id was not specified.
525538
this.id = this.id;
539+
540+
if (defaults) {
541+
if (defaults.disableOptionCentering != null) {
542+
this.disableOptionCentering = defaults.disableOptionCentering;
543+
}
544+
545+
if (defaults.typeaheadDebounceInterval != null) {
546+
this.typeaheadDebounceInterval = defaults.typeaheadDebounceInterval;
547+
}
548+
}
526549
}
527550

528551
ngOnInit() {

tools/public_api_guard/material/select.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export declare const MAT_SELECT_CONFIG: InjectionToken<MatSelectConfig>;
2+
13
export declare const MAT_SELECT_SCROLL_STRATEGY: InjectionToken<() => ScrollStrategy>;
24

35
export declare const MAT_SELECT_SCROLL_STRATEGY_PROVIDER: {
@@ -57,7 +59,7 @@ export declare class MatSelect extends _MatSelectMixinBase implements AfterConte
5759
typeaheadDebounceInterval: number;
5860
value: any;
5961
readonly valueChange: EventEmitter<any>;
60-
constructor(_viewportRuler: ViewportRuler, _changeDetectorRef: ChangeDetectorRef, _ngZone: NgZone, _defaultErrorStateMatcher: ErrorStateMatcher, elementRef: ElementRef, _dir: Directionality, _parentForm: NgForm, _parentFormGroup: FormGroupDirective, _parentFormField: MatFormField, ngControl: NgControl, tabIndex: string, scrollStrategyFactory: any, _liveAnnouncer: LiveAnnouncer);
62+
constructor(_viewportRuler: ViewportRuler, _changeDetectorRef: ChangeDetectorRef, _ngZone: NgZone, _defaultErrorStateMatcher: ErrorStateMatcher, elementRef: ElementRef, _dir: Directionality, _parentForm: NgForm, _parentFormGroup: FormGroupDirective, _parentFormField: MatFormField, ngControl: NgControl, tabIndex: string, scrollStrategyFactory: any, _liveAnnouncer: LiveAnnouncer, defaults?: MatSelectConfig);
6163
_calculateOverlayScroll(selectedIndex: number, scrollBuffer: number, maxScroll: number): number;
6264
_getAriaActiveDescendant(): string | null;
6365
_getAriaLabel(): string | null;
@@ -106,6 +108,11 @@ export declare class MatSelectChange {
106108
value: any);
107109
}
108110

111+
export interface MatSelectConfig {
112+
disableOptionCentering?: boolean;
113+
typeaheadDebounceInterval?: number;
114+
}
115+
109116
export declare class MatSelectModule {
110117
static ɵinj: i0.ɵɵInjectorDef<MatSelectModule>;
111118
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MatSelectModule, [typeof i1.MatSelect, typeof i1.MatSelectTrigger], [typeof i2.CommonModule, typeof i3.OverlayModule, typeof i4.MatOptionModule, typeof i4.MatCommonModule], [typeof i5.MatFormFieldModule, typeof i1.MatSelect, typeof i1.MatSelectTrigger, typeof i4.MatOptionModule, typeof i4.MatCommonModule]>;

0 commit comments

Comments
 (0)