Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/list/list-option.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
26 changes: 25 additions & 1 deletion src/lib/list/selection-list.spec.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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;

Expand Down
14 changes: 13 additions & 1 deletion src/lib/list/selection-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
Optional,
Output,
QueryList,
ViewChild,
ViewEncapsulation,
} from '@angular/core';
import {
Expand Down Expand Up @@ -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';

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down