Skip to content

Commit 83833c9

Browse files
committed
Move input event handling from chip-list to chip-input (no tests changes yet)
1 parent 9c981e9 commit 83833c9

File tree

2 files changed

+52
-54
lines changed

2 files changed

+52
-54
lines changed

src/material/chips/chip-input.ts

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

99
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
10-
import {Directive, ElementRef, EventEmitter, Inject, Input, OnChanges, Output} from '@angular/core';
11-
import {hasModifierKey, TAB} from '@angular/cdk/keycodes';
10+
import {
11+
Directive,
12+
ElementRef,
13+
EventEmitter,
14+
Inject,
15+
Input,
16+
OnChanges,
17+
Output,
18+
OnDestroy,
19+
AfterContentInit,
20+
} from '@angular/core';
21+
import {hasModifierKey, TAB, BACKSPACE} from '@angular/cdk/keycodes';
1222
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
1323
import {MatChipList} from './chip-list';
1424
import {MatChipTextControl} from './chip-text-control';
@@ -36,6 +46,7 @@ let nextUniqueId = 0;
3646
host: {
3747
'class': 'mat-chip-input mat-input-element',
3848
'(keydown)': '_keydown($event)',
49+
'(keyup)': '_keyup($event)',
3950
'(blur)': '_blur()',
4051
'(focus)': '_focus()',
4152
'(input)': '_onInput()',
@@ -46,7 +57,10 @@ let nextUniqueId = 0;
4657
'[attr.aria-required]': '_chipList && _chipList.required || null',
4758
}
4859
})
49-
export class MatChipInput implements MatChipTextControl, OnChanges {
60+
export class MatChipInput implements MatChipTextControl, OnChanges, OnDestroy, AfterContentInit {
61+
/** Used to prevent focus moving to chips while user is holding backspace */
62+
private _focusLastChipOnBackspace: boolean;
63+
5064
/** Whether the control is focused. */
5165
focused: boolean = false;
5266
_chipList: MatChipList;
@@ -104,21 +118,50 @@ export class MatChipInput implements MatChipTextControl, OnChanges {
104118
this._inputElement = this._elementRef.nativeElement as HTMLInputElement;
105119
}
106120

107-
ngOnChanges() {
121+
ngOnChanges(): void {
108122
this._chipList.stateChanges.next();
109123
}
110124

125+
ngOnDestroy(): void {
126+
this.chipEnd.complete();
127+
}
128+
129+
ngAfterContentInit(): void {
130+
this._focusLastChipOnBackspace = this.empty;
131+
}
132+
111133
/** Utility method to make host definition/tests more clear. */
112134
_keydown(event?: KeyboardEvent) {
113-
// Allow the user's focus to escape when they're tabbing forward. Note that we don't
114-
// want to do this when going backwards, because focus should go back to the first chip.
115-
if (event && event.keyCode === TAB && !hasModifierKey(event, 'shiftKey')) {
116-
this._chipList._allowFocusEscape();
135+
if (event) {
136+
// Allow the user's focus to escape when they're tabbing forward. Note that we don't
137+
// want to do this when going backwards, because focus should go back to the first chip.
138+
if (event.keyCode === TAB && !hasModifierKey(event, 'shiftKey')) {
139+
this._chipList._allowFocusEscape();
140+
}
141+
142+
if (event.keyCode === BACKSPACE && this._focusLastChipOnBackspace) {
143+
this._chipList._keyManager.setLastItemActive();
144+
event.preventDefault();
145+
return;
146+
} else {
147+
this._focusLastChipOnBackspace = false;
148+
}
117149
}
118150

119151
this._emitChipEnd(event);
120152
}
121153

154+
/**
155+
* Pass events to the keyboard manager. Available here for tests.
156+
*/
157+
_keyup(event: KeyboardEvent) {
158+
// Allow user to move focus to chips next time he presses backspace
159+
if (!this._focusLastChipOnBackspace && event.keyCode === BACKSPACE && this.empty) {
160+
this._focusLastChipOnBackspace = true;
161+
event.preventDefault();
162+
}
163+
}
164+
122165
/** Checks to see if the blur should emit the (chipEnd) event. */
123166
_blur() {
124167
if (this.addOnBlur) {

src/material/chips/chip-list.ts

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {FocusKeyManager} from '@angular/cdk/a11y';
1010
import {Directionality} from '@angular/cdk/bidi';
1111
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
1212
import {SelectionModel} from '@angular/cdk/collections';
13-
import {BACKSPACE, END, HOME} from '@angular/cdk/keycodes';
13+
import {END, HOME} from '@angular/cdk/keycodes';
1414
import {
1515
AfterContentInit,
1616
ChangeDetectionStrategy,
@@ -92,7 +92,6 @@ export class MatChipListChange {
9292
'(focus)': 'focus()',
9393
'(blur)': '_blur()',
9494
'(keydown)': '_keydown($event)',
95-
'(keyup)': '_keyup($event)',
9695
'[id]': '_uid',
9796
},
9897
providers: [{provide: MatFormFieldControl, useExisting: MatChipList}],
@@ -130,9 +129,6 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
130129
/** Subscription to remove changes in chips. */
131130
private _chipRemoveSubscription: Subscription | null;
132131

133-
/** Used to prevent focus moving to chips while user is holding backspace */
134-
private _focusLastChipOnBackspace: boolean;
135-
136132
/** The chip input to add more chips */
137133
protected _chipInput: MatChipTextControl;
138134

@@ -421,7 +417,6 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
421417
/** Associates an HTML input element with this chip list. */
422418
registerInput(inputElement: MatChipTextControl): void {
423419
this._chipInput = inputElement;
424-
this._focusLastChipOnBackspace = inputElement.empty;
425420
}
426421

427422
/**
@@ -498,17 +493,6 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
498493
_keydown(event: KeyboardEvent) {
499494
const target = event.target as HTMLElement;
500495

501-
// After input became empty and backspace was pressed again, focus last chip
502-
if (this._isInputElement(target)) {
503-
if (event.keyCode === BACKSPACE && this._focusLastChipOnBackspace) {
504-
this._keyManager.setLastItemActive();
505-
event.preventDefault();
506-
} else {
507-
this._focusLastChipOnBackspace = false;
508-
}
509-
return;
510-
}
511-
512496
if (target && target.classList.contains('mat-chip')) {
513497
if (event.keyCode === HOME) {
514498
this._keyManager.setFirstItemActive();
@@ -524,23 +508,6 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
524508
}
525509
}
526510

527-
/**
528-
* Pass events to the keyboard manager. Available here for tests.
529-
*/
530-
_keyup(event: KeyboardEvent) {
531-
const target = event.target as HTMLElement;
532-
533-
// Allow user to move focus to chips next time he presses backspace
534-
if (
535-
!this._focusLastChipOnBackspace &&
536-
event.keyCode === BACKSPACE &&
537-
this._isInputEmpty(target)
538-
) {
539-
this._focusLastChipOnBackspace = true;
540-
event.preventDefault();
541-
}
542-
}
543-
544511
/**
545512
* Check the tab index as you should not be allowed to focus an empty list.
546513
*/
@@ -577,18 +544,6 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
577544
return index >= 0 && index < this.chips.length;
578545
}
579546

580-
private _isInputElement(element: HTMLElement): element is HTMLInputElement {
581-
return element && element.nodeName.toLowerCase() === 'input';
582-
}
583-
584-
private _isInputEmpty(element: HTMLElement): boolean {
585-
if (this._isInputElement(element)) {
586-
return !element.value;
587-
}
588-
589-
return false;
590-
}
591-
592547
_setSelectionByValue(value: any, isUserInput: boolean = true) {
593548
this._clearSelection();
594549
this.chips.forEach(chip => chip.deselect());

0 commit comments

Comments
 (0)