diff --git a/src/material-experimental/mdc-chips/chip-grid.spec.ts b/src/material-experimental/mdc-chips/chip-grid.spec.ts index 4a2dde5c3152..e2ec4bbb2ab1 100644 --- a/src/material-experimental/mdc-chips/chip-grid.spec.ts +++ b/src/material-experimental/mdc-chips/chip-grid.spec.ts @@ -7,7 +7,9 @@ import { LEFT_ARROW, RIGHT_ARROW, SPACE, - TAB + TAB, + HOME, + END } from '@angular/cdk/keycodes'; import { createFakeEvent, @@ -443,6 +445,55 @@ describe('MDC-based MatChipGrid', () => { expect(manager.activeRowIndex).toBe(0); expect(manager.activeColumnIndex).toBe(0); }); + + it('should move focus to the first chip when pressing HOME', () => { + setupStandardGrid(); + manager = chipGridInstance._keyManager; + + const nativeChips = chipGridNativeElement.querySelectorAll('mat-chip-row'); + const lastNativeChip = nativeChips[nativeChips.length - 1] as HTMLElement; + + const HOME_EVENT: KeyboardEvent = + createKeyboardEvent('keydown', HOME, undefined, lastNativeChip); + const array = chips.toArray(); + const lastItem = array[array.length - 1]; + + lastItem.focus(); + expect(manager.activeRowIndex).toBe(4); + expect(manager.activeColumnIndex).toBe(0); + + chipGridInstance._keydown(HOME_EVENT); + fixture.detectChanges(); + + expect(HOME_EVENT.defaultPrevented).toBe(true); + expect(manager.activeRowIndex).toBe(0); + expect(manager.activeColumnIndex).toBe(0); + }); + + it('should move focus to the last chip when pressing END', () => { + setupStandardGrid(); + manager = chipGridInstance._keyManager; + + const nativeChips = chipGridNativeElement.querySelectorAll('mat-chip-row'); + const firstNativeChip = nativeChips[0] as HTMLElement; + + const END_EVENT: KeyboardEvent = + createKeyboardEvent('keydown', END, undefined, firstNativeChip); + const array = chips.toArray(); + const firstItem = array[0]; + + firstItem.focus(); + expect(manager.activeRowIndex).toBe(0); + expect(manager.activeColumnIndex).toBe(0); + + chipGridInstance._keydown(END_EVENT); + fixture.detectChanges(); + + expect(END_EVENT.defaultPrevented).toBe(true); + expect(manager.activeRowIndex).toBe(4); + expect(manager.activeColumnIndex).toBe(0); + }); + }); }); diff --git a/src/material-experimental/mdc-chips/chip-grid.ts b/src/material-experimental/mdc-chips/chip-grid.ts index 70d09e63cf1e..436dae1bafbb 100644 --- a/src/material-experimental/mdc-chips/chip-grid.ts +++ b/src/material-experimental/mdc-chips/chip-grid.ts @@ -8,7 +8,7 @@ import {Directionality} from '@angular/cdk/bidi'; import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion'; -import {BACKSPACE, TAB} from '@angular/cdk/keycodes'; +import {BACKSPACE, TAB, HOME, END} from '@angular/cdk/keycodes'; import { AfterContentInit, AfterViewInit, @@ -400,17 +400,27 @@ export class MatChipGrid extends _MatChipGridMixinBase implements AfterContentIn /** Handles custom keyboard events. */ _keydown(event: KeyboardEvent) { const target = event.target as HTMLElement; + const keyCode = event.keyCode; + const manager = this._keyManager; // If they are on an empty input and hit backspace, focus the last chip - if (event.keyCode === BACKSPACE && this._isEmptyInput(target)) { + if (keyCode === BACKSPACE && this._isEmptyInput(target)) { if (this._chips.length) { - this._keyManager.setLastCellActive(); + manager.setLastCellActive(); } event.preventDefault(); - } else if (event.keyCode === TAB && target.id !== this._chipInput!.id ) { + } else if (keyCode === TAB && target.id !== this._chipInput!.id ) { this._allowFocusEscape(); } else if (this._originatesFromChip(event)) { - this._keyManager.onKeydown(event); + if (keyCode === HOME) { + manager.setFirstCellActive(); + event.preventDefault(); + } else if (keyCode === END) { + manager.setLastCellActive(); + event.preventDefault(); + } else { + manager.onKeydown(event); + } } this.stateChanges.next(); }