diff --git a/src/lib/list/list-option.html b/src/lib/list/list-option.html
index 4b6fb2aa5df4..db84f6f66dd6 100644
--- a/src/lib/list/list-option.html
+++ b/src/lib/list/list-option.html
@@ -7,10 +7,10 @@
[matRippleTrigger]="_getHostElement()"
[matRippleDisabled]="_isRippleDisabled()">
-
-
+
diff --git a/src/lib/list/selection-list.spec.ts b/src/lib/list/selection-list.spec.ts
index 876309677edb..9abb7c3416e2 100644
--- a/src/lib/list/selection-list.spec.ts
+++ b/src/lib/list/selection-list.spec.ts
@@ -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;
diff --git a/src/lib/list/selection-list.ts b/src/lib/list/selection-list.ts
index bcd8cfa7767a..ce682df8abc2 100644
--- a/src/lib/list/selection-list.ts
+++ b/src/lib/list/selection-list.ts
@@ -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;
+ /** 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(this.options).withWrap();
+ this._keyManager = new FocusKeyManager(this.options).withWrap().withTypeAhead();
if (this._tempValues) {
this._setOptionsFromValues(this._tempValues);