Skip to content

Commit

Permalink
fix(chips): chip list removing focus from first chip when adding thro…
Browse files Browse the repository at this point in the history
…ugh 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.
  • Loading branch information
crisbeto authored and jelbourn committed Aug 26, 2018
1 parent cfa2d04 commit c3b2d4f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
36 changes: 35 additions & 1 deletion src/lib/chips/chip-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
dispatchFakeEvent,
dispatchKeyboardEvent,
dispatchMouseEvent,
typeInElement,
MockNgZone,
} from '@angular/cdk/testing';
import {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -1322,7 +1348,7 @@ class MultiSelectionChipList {
<mat-form-field>
<mat-chip-list [multiple]="true"
placeholder="Food" [formControl]="control" [required]="isRequired" #chipList1>
<mat-chip *ngFor="let food of foods" [value]="food.value">
<mat-chip *ngFor="let food of foods" [value]="food.value" (removed)="remove(food)">
{{ food.viewValue }}
</mat-chip>
</mat-chip-list>
Expand Down Expand Up @@ -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<MatChip>;
}
Expand Down
13 changes: 5 additions & 8 deletions src/lib/chips/chip-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit c3b2d4f

Please sign in to comment.