From 3723191be819522b14e7640bbb073caf02d74be2 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 23 Aug 2018 22:26:52 +0200 Subject: [PATCH] fix(chips): support focusing first/last item using home/end (#11892) Based on the accessibility guidelines, grid cells should support moving focus to the first/last items via the Home and End keys. --- src/lib/chips/chip-list.spec.ts | 42 ++++++++++++++++++++++++++++++++- src/lib/chips/chip-list.ts | 13 ++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/lib/chips/chip-list.spec.ts b/src/lib/chips/chip-list.spec.ts index 1a2abe95a00f..52f0c3b190b3 100644 --- a/src/lib/chips/chip-list.spec.ts +++ b/src/lib/chips/chip-list.spec.ts @@ -1,6 +1,16 @@ import {FocusKeyManager} from '@angular/cdk/a11y'; import {Directionality, Direction} from '@angular/cdk/bidi'; -import {BACKSPACE, DELETE, ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE, TAB} from '@angular/cdk/keycodes'; +import { + BACKSPACE, + DELETE, + ENTER, + LEFT_ARROW, + RIGHT_ARROW, + SPACE, + TAB, + HOME, + END, +} from '@angular/cdk/keycodes'; import { createKeyboardEvent, dispatchFakeEvent, @@ -296,6 +306,36 @@ describe('MatChipList', () => { .toBe(initialActiveIndex, 'Expected focused item not to have changed.'); }); + it('should focus the first item when pressing HOME', () => { + const nativeChips = chipListNativeElement.querySelectorAll('mat-chip'); + const lastNativeChip = nativeChips[nativeChips.length - 1] as HTMLElement; + const HOME_EVENT = createKeyboardEvent('keydown', HOME, lastNativeChip); + const array = chips.toArray(); + const lastItem = array[array.length - 1]; + + lastItem.focus(); + expect(manager.activeItemIndex).toBe(array.length - 1); + + chipListInstance._keydown(HOME_EVENT); + fixture.detectChanges(); + + expect(manager.activeItemIndex).toBe(0); + expect(HOME_EVENT.defaultPrevented).toBe(true); + }); + + it('should focus the last item when pressing END', () => { + const nativeChips = chipListNativeElement.querySelectorAll('mat-chip'); + const END_EVENT = createKeyboardEvent('keydown', END, nativeChips[0]); + + expect(manager.activeItemIndex).toBe(-1); + + chipListInstance._keydown(END_EVENT); + fixture.detectChanges(); + + expect(manager.activeItemIndex).toBe(chips.length - 1); + expect(END_EVENT.defaultPrevented).toBe(true); + }); + }); describe('RTL', () => { diff --git a/src/lib/chips/chip-list.ts b/src/lib/chips/chip-list.ts index 8f418e7a20cf..cf4f9bbd93f8 100644 --- a/src/lib/chips/chip-list.ts +++ b/src/lib/chips/chip-list.ts @@ -10,7 +10,7 @@ import {FocusKeyManager} from '@angular/cdk/a11y'; import {Directionality} from '@angular/cdk/bidi'; import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {SelectionModel} from '@angular/cdk/collections'; -import {BACKSPACE} from '@angular/cdk/keycodes'; +import {BACKSPACE, HOME, END} from '@angular/cdk/keycodes'; import { AfterContentInit, ChangeDetectionStrategy, @@ -483,7 +483,16 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo this._keyManager.setLastItemActive(); event.preventDefault(); } else if (target && target.classList.contains('mat-chip')) { - this._keyManager.onKeydown(event); + if (event.keyCode === HOME) { + this._keyManager.setFirstItemActive(); + event.preventDefault(); + } else if (event.keyCode === END) { + this._keyManager.setLastItemActive(); + event.preventDefault(); + } else { + this._keyManager.onKeydown(event); + } + this.stateChanges.next(); } }