fix(selection-list): allow users to jump focus to a particular item by typing (#9026)

Similarly to our other listbox-based components, this allows people to move focus to a particular item by typing the first letters of its label.
This commit is contained in:
Kristiyan Kostadinov
2018-01-08 20:20:07 +01:00
committed by Jeremy Elbourn
parent b8ff582fc9
commit af44b9dad7
3 changed files with 40 additions and 4 deletions
+2 -2
View File
@@ -7,10 +7,10 @@
[matRippleTrigger]="_getHostElement()"
[matRippleDisabled]="_isRippleDisabled()"></div>
<mat-pseudo-checkbox #autocheckbox
<mat-pseudo-checkbox
[state]="selected ? 'checked' : 'unchecked'"
[disabled]="disabled"></mat-pseudo-checkbox>
<div class="mat-list-text"><ng-content></ng-content></div>
<div class="mat-list-text" #text><ng-content></ng-content></div>
</div>
+25 -1
View File
@@ -1,6 +1,11 @@
import {DOWN_ARROW, SPACE, ENTER, UP_ARROW, HOME, END} from '@angular/cdk/keycodes';
import {Platform} from '@angular/cdk/platform';
import {createKeyboardEvent, dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing';
import {
createKeyboardEvent,
dispatchFakeEvent,
dispatchEvent,
dispatchKeyboardEvent,
} from '@angular/cdk/testing';
import {Component, DebugElement} from '@angular/core';
import {async, ComponentFixture, fakeAsync, inject, TestBed, tick} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
@@ -287,6 +292,25 @@ describe('MatSelectionList without forms', () => {
expect(event.defaultPrevented).toBe(true);
});
it('should be able to jump focus down to an item by typing', fakeAsync(() => {
const listEl = selectionList.nativeElement;
const manager = selectionList.componentInstance._keyManager;
expect(manager.activeItemIndex).toBe(-1);
dispatchEvent(listEl, createKeyboardEvent('keydown', 83, undefined, 's'));
fixture.detectChanges();
tick(200);
expect(manager.activeItemIndex).toBe(1);
dispatchEvent(listEl, createKeyboardEvent('keydown', 68, undefined, 'd'));
fixture.detectChanges();
tick(200);
expect(manager.activeItemIndex).toBe(3);
}));
it('should be able to select all options', () => {
const list: MatSelectionList = selectionList.componentInstance;
+13 -1
View File
@@ -27,6 +27,7 @@ import {
Optional,
Output,
QueryList,
ViewChild,
ViewEncapsulation,
} from '@angular/core';
import {
@@ -118,6 +119,9 @@ export class MatListOption extends _MatListOptionMixinBase
@ContentChildren(MatLine) _lines: QueryList<MatLine>;
/** DOM element containing the item's text. */
@ViewChild('text') _text: ElementRef;
/** Whether the label should appear before or after the checkbox. Defaults to 'after' */
@Input() checkboxPosition: 'before' | 'after' = 'after';
@@ -197,6 +201,14 @@ export class MatListOption extends _MatListOptionMixinBase
this._element.nativeElement.focus();
}
/**
* Returns the list item's text label. Implemented as a part of the FocusKeyManager.
* @docs-private
*/
getLabel() {
return this._text ? this._text.nativeElement.textContent : '';
}
/** Whether this list item should show a ripple effect when clicked. */
_isRippleDisabled() {
return this.disabled || this.disableRipple || this.selectionList.disableRipple;
@@ -309,7 +321,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
}
ngAfterContentInit(): void {
this._keyManager = new FocusKeyManager<MatListOption>(this.options).withWrap();
this._keyManager = new FocusKeyManager<MatListOption>(this.options).withWrap().withTypeAhead();
if (this._tempValues) {
this._setOptionsFromValues(this._tempValues);