fix(stepper): don't handle enter/space when modifier key is pressed (#13827)

Along the same lines as #13790. Doesn't handle the prevent the default action for ENTER and SPACE when one of the modifier keys is pressed, in order to avoid interefering with the native keyboard shortcuts.
This commit is contained in:
Kristiyan Kostadinov
2018-10-29 16:14:08 +01:00
committed by Jeremy Elbourn
parent a22a9fa3d7
commit a9e550e5bf
2 changed files with 53 additions and 6 deletions
+10 -5
View File
@@ -442,19 +442,24 @@ export class CdkStepper implements AfterViewInit, OnDestroy {
}
_onKeydown(event: KeyboardEvent) {
// TODO(crisbeto): move into a CDK utility once
// the similar PRs for other components are merged in.
const hasModifier = event.altKey || event.shiftKey || event.ctrlKey || event.metaKey;
const keyCode = event.keyCode;
const manager = this._keyManager;
if (this._keyManager.activeItemIndex != null && (keyCode === SPACE || keyCode === ENTER)) {
this.selectedIndex = this._keyManager.activeItemIndex;
if (manager.activeItemIndex != null && !hasModifier &&
(keyCode === SPACE || keyCode === ENTER)) {
this.selectedIndex = manager.activeItemIndex;
event.preventDefault();
} else if (keyCode === HOME) {
this._keyManager.setFirstItemActive();
manager.setFirstItemActive();
event.preventDefault();
} else if (keyCode === END) {
this._keyManager.setLastItemActive();
manager.setLastItemActive();
event.preventDefault();
} else {
this._keyManager.onKeydown(event);
manager.onKeydown(event);
}
}
+43 -1
View File
@@ -10,7 +10,7 @@ import {
UP_ARROW,
} from '@angular/cdk/keycodes';
import {StepperOrientation, MAT_STEPPER_GLOBAL_OPTIONS, STEP_STATE} from '@angular/cdk/stepper';
import {dispatchKeyboardEvent} from '@angular/cdk/testing';
import {dispatchKeyboardEvent, createKeyboardEvent, dispatchEvent} from '@angular/cdk/testing';
import {Component, DebugElement, EventEmitter, OnInit, Type, Provider} from '@angular/core';
import {ComponentFixture, fakeAsync, flush, inject, TestBed} from '@angular/core/testing';
import {
@@ -345,6 +345,16 @@ describe('MatStepper', () => {
expect(stepperComponent.selectedIndex).toBe(1);
});
it('should not do anything when pressing the ENTER key with a modifier', () => {
const stepHeaders = fixture.debugElement.queryAll(By.css('.mat-vertical-stepper-header'));
assertSelectKeyWithModifierInteraction(fixture, stepHeaders, 'vertical', ENTER);
});
it('should not do anything when pressing the SPACE key with a modifier', () => {
const stepHeaders = fixture.debugElement.queryAll(By.css('.mat-vertical-stepper-header'));
assertSelectKeyWithModifierInteraction(fixture, stepHeaders, 'vertical', SPACE);
});
});
describe('basic stepper when attempting to set the selected step too early', () => {
@@ -1063,6 +1073,38 @@ function assertArrowKeyInteractionInRtl(fixture: ComponentFixture<any>,
expect(stepperComponent._getFocusIndex()).toBe(0);
}
/** Asserts that keyboard interaction works correctly when the user is pressing a modifier key. */
function assertSelectKeyWithModifierInteraction(fixture: ComponentFixture<any>,
stepHeaders: DebugElement[],
orientation: StepperOrientation,
selectionKey: number) {
const stepperComponent = fixture.debugElement.query(By.directive(MatStepper)).componentInstance;
const modifiers = ['altKey', 'shiftKey', 'ctrlKey', 'metaKey'];
expect(stepperComponent._getFocusIndex()).toBe(0);
expect(stepperComponent.selectedIndex).toBe(0);
dispatchKeyboardEvent(stepHeaders[0].nativeElement, 'keydown',
orientation === 'vertical' ? DOWN_ARROW : RIGHT_ARROW);
fixture.detectChanges();
expect(stepperComponent._getFocusIndex())
.toBe(1, 'Expected index of focused step to increase by 1 after pressing the next key.');
expect(stepperComponent.selectedIndex)
.toBe(0, 'Expected index of selected step to remain unchanged after pressing the next key.');
modifiers.forEach(modifier => {
const event: KeyboardEvent = createKeyboardEvent('keydown', selectionKey);
Object.defineProperty(event, modifier, {get: () => true});
dispatchEvent(stepHeaders[1].nativeElement, event);
fixture.detectChanges();
expect(stepperComponent.selectedIndex).toBe(0, `Expected selected index to remain unchanged ` +
`when pressing the selection key with ${modifier} modifier.`);
expect(event.defaultPrevented).toBe(false);
});
}
function asyncValidator(minLength: number, validationTrigger: Subject<void>): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => {
return validationTrigger.pipe(