From 889faee811fc78d9f2971ddcd82ae6ab5c02b465 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sun, 26 Aug 2018 16:06:06 +0200 Subject: [PATCH] fix(chips): chip list removing focus from first chip when adding through the input Something I ran into while aligning the chips with the new spec, which seems to have been introduced in 3da390e36df3a3f63695535c4f9fdac9b137eaee. 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. --- src/lib/chips/chip-list.spec.ts | 36 ++++++++++++++++++++++++++++++++- src/lib/chips/chip-list.ts | 13 +++++------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/lib/chips/chip-list.spec.ts b/src/lib/chips/chip-list.spec.ts index f39987cbfa6a..da3239147f63 100644 --- a/src/lib/chips/chip-list.spec.ts +++ b/src/lib/chips/chip-list.spec.ts @@ -17,6 +17,7 @@ import { dispatchFakeEvent, dispatchKeyboardEvent, dispatchMouseEvent, + typeInElement, MockNgZone, } from '@angular/cdk/testing'; import { @@ -993,6 +994,31 @@ describe('MatChipList', () => { .not.toBeNull(`Expected placeholder to have an asterisk, as control was required.`); }); + it('should keep focus on the input after adding the first chip', fakeAsync(() => { + const nativeInput = fixture.nativeElement.querySelector('input'); + const chipEls = Array.from(fixture.nativeElement.querySelectorAll('.mat-chip')).reverse(); + + // Remove the chips via backspace to simulate the user removing them. + chipEls.forEach((chip: HTMLElement) => { + chip.focus(); + dispatchKeyboardEvent(chip, 'keydown', BACKSPACE); + fixture.detectChanges(); + tick(); + }); + + nativeInput.focus(); + expect(fixture.componentInstance.foods).toEqual([], 'Expected all chips to be removed.'); + expect(document.activeElement).toBe(nativeInput, 'Expected input to be focused.'); + + typeInElement('123', nativeInput); + fixture.detectChanges(); + dispatchKeyboardEvent(nativeInput, 'keydown', ENTER); + fixture.detectChanges(); + tick(); + + expect(document.activeElement).toBe(nativeInput, 'Expected input to remain focused.'); + })); + describe('keyboard behavior', () => { beforeEach(() => { chipListDebugElement = fixture.debugElement.query(By.directive(MatChipList)); @@ -1322,7 +1348,7 @@ class MultiSelectionChipList { - + {{ food.viewValue }} @@ -1369,6 +1395,14 @@ class InputChipList { } } + remove(food: any): void { + const index = this.foods.indexOf(food); + + if (index > -1) { + this.foods.splice(index, 1); + } + } + @ViewChild(MatChipList) chipList: MatChipList; @ViewChildren(MatChip) chips: QueryList; } diff --git a/src/lib/chips/chip-list.ts b/src/lib/chips/chip-list.ts index 3e0701692051..1e2074a90997 100644 --- a/src/lib/chips/chip-list.ts +++ b/src/lib/chips/chip-list.ts @@ -498,18 +498,15 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo } /** - * If the amount of chips changed, we need to update the key manager state and make sure - * that to so that we can refocus the - * next closest one. + * If the amount of chips changed, we need to update the + * key manager state and focus the next closest chip. */ protected _updateFocusForDestroyedChips() { - if (this._lastDestroyedChipIndex == null || !this.chips.length) { - return; + if (this._lastDestroyedChipIndex != null && this.chips.length) { + const newChipIndex = Math.min(this._lastDestroyedChipIndex, this.chips.length - 1); + this._keyManager.setActiveItem(newChipIndex); } - const newChipIndex = Math.min(this._lastDestroyedChipIndex, this.chips.length - 1); - - this._keyManager.setActiveItem(newChipIndex); this._lastDestroyedChipIndex = null; }