Skip to content

Commit 3c8a498

Browse files
crisbetoandrewseguin
authored andcommitted
feat(chips): allow for separatorKeyCodes to be configured globally (#10264)
Adds the `MAT_CHIPS_DEFAULT_OPTIONS` injection token that allows consumers to override `separatorKeyCodes`, as well as any other options that we decide to add in the future, for the entire module. Fixes #10256.
1 parent 9a1ae9c commit 3c8a498

File tree

6 files changed

+94
-14
lines changed

6 files changed

+94
-14
lines changed

src/lib/chips/chip-default-options.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {InjectionToken} from '@angular/core';
10+
11+
/** Default options, for the chips module, that can be overridden. */
12+
export interface MatChipsDefaultOptions {
13+
/** The list of key codes that will trigger a chipEnd event. */
14+
separatorKeyCodes: number[];
15+
}
16+
17+
/** Injection token to be used to override the default options for the chips module. */
18+
export const MAT_CHIPS_DEFAULT_OPTIONS =
19+
new InjectionToken<MatChipsDefaultOptions>('mat-chips-default-options');

src/lib/chips/chip-input.spec.ts

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
77
import {By} from '@angular/platform-browser';
88
import {MatChipInput, MatChipInputEvent} from './chip-input';
99
import {MatChipsModule} from './index';
10+
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
1011

1112

1213
describe('MatChipInput', () => {
@@ -44,7 +45,7 @@ describe('MatChipInput', () => {
4445

4546
describe('basic behavior', () => {
4647
it('emits the (chipEnd) on enter keyup', () => {
47-
let ENTER_EVENT = createKeyboardEvent('keydown', ENTER, inputNativeElement) as any;
48+
let ENTER_EVENT = createKeyboardEvent('keydown', ENTER, inputNativeElement);
4849

4950
spyOn(testChipInput, 'add');
5051

@@ -79,28 +80,59 @@ describe('MatChipInput', () => {
7980
});
8081
});
8182

82-
describe('[separatorKeysCodes]', () => {
83+
describe('[separatorKeyCodes]', () => {
8384
it('does not emit (chipEnd) when a non-separator key is pressed', () => {
84-
let ENTER_EVENT = createKeyboardEvent('keydown', ENTER, inputNativeElement) as any;
85+
let ENTER_EVENT = createKeyboardEvent('keydown', ENTER, inputNativeElement);
8586
spyOn(testChipInput, 'add');
8687

87-
testChipInput.separatorKeys = [COMMA];
88+
chipInputDirective.separatorKeyCodes = [COMMA];
8889
fixture.detectChanges();
8990

9091
chipInputDirective._keydown(ENTER_EVENT);
9192
expect(testChipInput.add).not.toHaveBeenCalled();
9293
});
9394

9495
it('emits (chipEnd) when a custom separator keys is pressed', () => {
95-
let COMMA_EVENT = createKeyboardEvent('keydown', COMMA, inputNativeElement) as any;
96+
let COMMA_EVENT = createKeyboardEvent('keydown', COMMA, inputNativeElement);
9697
spyOn(testChipInput, 'add');
9798

98-
testChipInput.separatorKeys = [COMMA];
99+
chipInputDirective.separatorKeyCodes = [COMMA];
99100
fixture.detectChanges();
100101

101102
chipInputDirective._keydown(COMMA_EVENT);
102103
expect(testChipInput.add).toHaveBeenCalled();
103104
});
105+
106+
it('emits (chipEnd) when the separator keys are configured globally', () => {
107+
fixture.destroy();
108+
109+
TestBed
110+
.resetTestingModule()
111+
.configureTestingModule({
112+
imports: [MatChipsModule, PlatformModule],
113+
declarations: [TestChipInput],
114+
providers: [{
115+
provide: MAT_CHIPS_DEFAULT_OPTIONS,
116+
useValue: ({separatorKeyCodes: [COMMA]} as MatChipsDefaultOptions)
117+
}]
118+
})
119+
.compileComponents();
120+
121+
fixture = TestBed.createComponent(TestChipInput);
122+
testChipInput = fixture.debugElement.componentInstance;
123+
fixture.detectChanges();
124+
125+
inputDebugElement = fixture.debugElement.query(By.directive(MatChipInput));
126+
chipInputDirective = inputDebugElement.injector.get(MatChipInput) as MatChipInput;
127+
inputNativeElement = inputDebugElement.nativeElement;
128+
129+
spyOn(testChipInput, 'add');
130+
fixture.detectChanges();
131+
132+
chipInputDirective._keydown(createKeyboardEvent('keydown', COMMA, inputNativeElement));
133+
expect(testChipInput.add).toHaveBeenCalled();
134+
});
135+
104136
});
105137
});
106138

@@ -110,13 +142,11 @@ describe('MatChipInput', () => {
110142
</mat-chip-list>
111143
<input matInput [matChipInputFor]="chipList"
112144
[matChipInputAddOnBlur]="addOnBlur"
113-
[matChipInputSeparatorKeyCodes]="separatorKeys"
114145
(matChipInputTokenEnd)="add($event)" />
115146
`
116147
})
117148
class TestChipInput {
118149
addOnBlur: boolean = false;
119-
separatorKeys: number[] = [ENTER];
120150

121151
add(_: MatChipInputEvent) {
122152
}

src/lib/chips/chip-input.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
*/
88

99
import {coerceBooleanProperty} from '@angular/cdk/coercion';
10-
import {ENTER} from '@angular/cdk/keycodes';
11-
import {Directive, ElementRef, EventEmitter, Input, Output} from '@angular/core';
10+
import {Directive, ElementRef, EventEmitter, Input, Output, Inject} from '@angular/core';
1211
import {MatChipList} from './chip-list';
12+
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
1313

1414

1515
/** Represents an input event on a `matChipInput`. */
@@ -68,7 +68,8 @@ export class MatChipInput {
6868
* Defaults to `[ENTER]`.
6969
*/
7070
// TODO(tinayuangao): Support Set here
71-
@Input('matChipInputSeparatorKeyCodes') separatorKeyCodes: number[] = [ENTER];
71+
@Input('matChipInputSeparatorKeyCodes')
72+
separatorKeyCodes: number[] = this._defaultOptions.separatorKeyCodes;
7273

7374
/** Emitted when a chip is to be added. */
7475
@Output('matChipInputTokenEnd')
@@ -86,7 +87,9 @@ export class MatChipInput {
8687
/** The native input element to which this directive is attached. */
8788
protected _inputElement: HTMLInputElement;
8889

89-
constructor(protected _elementRef: ElementRef) {
90+
constructor(
91+
protected _elementRef: ElementRef,
92+
@Inject(MAT_CHIPS_DEFAULT_OPTIONS) private _defaultOptions: MatChipsDefaultOptions) {
9093
this._inputElement = this._elementRef.nativeElement as HTMLInputElement;
9194
}
9295

src/lib/chips/chips-module.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {ErrorStateMatcher} from '@angular/material/core';
1212
import {MatChip, MatChipAvatar, MatChipRemove, MatChipTrailingIcon} from './chip';
1313
import {MatChipInput} from './chip-input';
1414
import {MatChipList} from './chip-list';
15+
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
16+
import {ENTER} from '@angular/cdk/keycodes';
1517

1618
const CHIP_DECLARATIONS = [
1719
MatChipList,
@@ -26,6 +28,14 @@ const CHIP_DECLARATIONS = [
2628
imports: [PlatformModule],
2729
exports: CHIP_DECLARATIONS,
2830
declarations: CHIP_DECLARATIONS,
29-
providers: [ErrorStateMatcher]
31+
providers: [
32+
ErrorStateMatcher,
33+
{
34+
provide: MAT_CHIPS_DEFAULT_OPTIONS,
35+
useValue: {
36+
separatorKeyCodes: [ENTER]
37+
} as MatChipsDefaultOptions
38+
}
39+
]
3040
})
3141
export class MatChipsModule {}

src/lib/chips/chips.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ _Hint: `<mat-basic-chip>` receives the `mat-basic-chip` CSS class in addition to
2020
Chips can be selected via the `selected` property. Selection can be disabled by setting
2121
`selectable` to `false` on the `<mat-chip-list>`.
2222

23-
Whenever the selection state changes, a `ChipSelectionChange` event will be emitted via
23+
Whenever the selection state changes, a `ChipSelectionChange` event will be emitted via
2424
`(selectionChange)`.
2525

2626
### Disabled chips
@@ -67,6 +67,23 @@ the `mat-chip-list-stacked` class, as well as the `aria-orientation="vertical"`
6767
</mat-chip-list>
6868
```
6969

70+
### Specifying global configuration defaults
71+
Default options for the chips module can be specified using the `MAT_CHIPS_DEFAULT_OPTIONS`
72+
injection token.
73+
74+
```ts
75+
@NgModule({
76+
providers: [
77+
{
78+
provide: MAT_CHIPS_DEFAULT_OPTIONS,
79+
useValue: {
80+
separatorKeyCodes: [ENTER, COMMA]
81+
}
82+
}
83+
]
84+
})
85+
```
86+
7087
### Theming
7188
The selected color of an `<mat-chip>` can be changed by using the `color` property. By default, chips
7289
use a neutral background color based on the current theme (light or dark). This can be changed to

src/lib/chips/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './chips-module';
1010
export * from './chip-list';
1111
export * from './chip';
1212
export * from './chip-input';
13+
export * from './chip-default-options';

0 commit comments

Comments
 (0)