Skip to content

Commit c3b2d4f

Browse files
crisbetojelbourn
authored andcommitted
fix(chips): chip list removing focus from first chip when adding through the input (#12840)
Fix regression in 3da390e. Currently when the user removes all the chips and then they add a new chip, the chip list will remove focus from the input and put it on the chip. These changes introduce the proper behavior, which is to keep focus on the input.
1 parent cfa2d04 commit c3b2d4f

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
dispatchFakeEvent,
1818
dispatchKeyboardEvent,
1919
dispatchMouseEvent,
20+
typeInElement,
2021
MockNgZone,
2122
} from '@angular/cdk/testing';
2223
import {
@@ -993,6 +994,31 @@ describe('MatChipList', () => {
993994
.not.toBeNull(`Expected placeholder to have an asterisk, as control was required.`);
994995
});
995996

997+
it('should keep focus on the input after adding the first chip', fakeAsync(() => {
998+
const nativeInput = fixture.nativeElement.querySelector('input');
999+
const chipEls = Array.from(fixture.nativeElement.querySelectorAll('.mat-chip')).reverse();
1000+
1001+
// Remove the chips via backspace to simulate the user removing them.
1002+
chipEls.forEach((chip: HTMLElement) => {
1003+
chip.focus();
1004+
dispatchKeyboardEvent(chip, 'keydown', BACKSPACE);
1005+
fixture.detectChanges();
1006+
tick();
1007+
});
1008+
1009+
nativeInput.focus();
1010+
expect(fixture.componentInstance.foods).toEqual([], 'Expected all chips to be removed.');
1011+
expect(document.activeElement).toBe(nativeInput, 'Expected input to be focused.');
1012+
1013+
typeInElement('123', nativeInput);
1014+
fixture.detectChanges();
1015+
dispatchKeyboardEvent(nativeInput, 'keydown', ENTER);
1016+
fixture.detectChanges();
1017+
tick();
1018+
1019+
expect(document.activeElement).toBe(nativeInput, 'Expected input to remain focused.');
1020+
}));
1021+
9961022
describe('keyboard behavior', () => {
9971023
beforeEach(() => {
9981024
chipListDebugElement = fixture.debugElement.query(By.directive(MatChipList));
@@ -1322,7 +1348,7 @@ class MultiSelectionChipList {
13221348
<mat-form-field>
13231349
<mat-chip-list [multiple]="true"
13241350
placeholder="Food" [formControl]="control" [required]="isRequired" #chipList1>
1325-
<mat-chip *ngFor="let food of foods" [value]="food.value">
1351+
<mat-chip *ngFor="let food of foods" [value]="food.value" (removed)="remove(food)">
13261352
{{ food.viewValue }}
13271353
</mat-chip>
13281354
</mat-chip-list>
@@ -1369,6 +1395,14 @@ class InputChipList {
13691395
}
13701396
}
13711397

1398+
remove(food: any): void {
1399+
const index = this.foods.indexOf(food);
1400+
1401+
if (index > -1) {
1402+
this.foods.splice(index, 1);
1403+
}
1404+
}
1405+
13721406
@ViewChild(MatChipList) chipList: MatChipList;
13731407
@ViewChildren(MatChip) chips: QueryList<MatChip>;
13741408
}

src/lib/chips/chip-list.ts

+5-8
Original file line numberDiff line numberDiff line change
@@ -498,18 +498,15 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
498498
}
499499

500500
/**
501-
* If the amount of chips changed, we need to update the key manager state and make sure
502-
* that to so that we can refocus the
503-
* next closest one.
501+
* If the amount of chips changed, we need to update the
502+
* key manager state and focus the next closest chip.
504503
*/
505504
protected _updateFocusForDestroyedChips() {
506-
if (this._lastDestroyedChipIndex == null || !this.chips.length) {
507-
return;
505+
if (this._lastDestroyedChipIndex != null && this.chips.length) {
506+
const newChipIndex = Math.min(this._lastDestroyedChipIndex, this.chips.length - 1);
507+
this._keyManager.setActiveItem(newChipIndex);
508508
}
509509

510-
const newChipIndex = Math.min(this._lastDestroyedChipIndex, this.chips.length - 1);
511-
512-
this._keyManager.setActiveItem(newChipIndex);
513510
this._lastDestroyedChipIndex = null;
514511
}
515512

0 commit comments

Comments
 (0)