Skip to content

Commit b15b8be

Browse files
crisbetojelbourn
authored andcommitted
fix(stepper): handle keyboard interactions if direction changes after init (#11067)
Currently the stepper checks for its direction once on init, in order to configure its keyboard control direction, however this doesn't account for the cases where the direction changes dynamically afterwards. These changes ensure that the keyboard controls are correct in case the layout direction changes.
1 parent 408134f commit b15b8be

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import {
3333
} from '@angular/core';
3434
import {AbstractControl} from '@angular/forms';
3535
import {CdkStepLabel} from './step-label';
36-
import {Subject} from 'rxjs';
36+
import {Observable, Subject, of as obaservableOf} from 'rxjs';
37+
import {startWith, takeUntil} from 'rxjs/operators';
3738

3839
/** Used to generate unique ID for each stepper component. */
3940
let nextId = 0;
@@ -215,9 +216,12 @@ export class CdkStepper implements AfterViewInit, OnDestroy {
215216
ngAfterViewInit() {
216217
this._keyManager = new FocusKeyManager(this._stepHeader)
217218
.withWrap()
218-
.withHorizontalOrientation(this._layoutDirection())
219219
.withVerticalOrientation(this._orientation === 'vertical');
220220

221+
(this._dir ? this._dir.change as Observable<Direction> : obaservableOf())
222+
.pipe(startWith(this._layoutDirection()), takeUntil(this._destroyed))
223+
.subscribe(direction => this._keyManager.withHorizontalOrientation(direction));
224+
221225
this._keyManager.updateActiveItemIndex(this._selectedIndex);
222226
}
223227

src/lib/stepper/stepper.spec.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '@angular/cdk/keycodes';
1212
import {StepperOrientation} from '@angular/cdk/stepper';
1313
import {dispatchKeyboardEvent} from '@angular/cdk/testing';
14-
import {Component, DebugElement} from '@angular/core';
14+
import {Component, DebugElement, EventEmitter} from '@angular/core';
1515
import {async, ComponentFixture, inject, TestBed, fakeAsync, flush} from '@angular/core/testing';
1616
import {
1717
AbstractControl,
@@ -35,10 +35,13 @@ import {MatStepperIntl} from './stepper-intl';
3535
const VALID_REGEX = /valid/;
3636

3737
describe('MatStepper', () => {
38-
let dir: Direction;
38+
let dir: {value: Direction, change: EventEmitter<Direction>};
3939

4040
beforeEach(async(() => {
41-
dir = 'ltr';
41+
dir = {
42+
value: 'ltr',
43+
change: new EventEmitter()
44+
};
4245

4346
TestBed.configureTestingModule({
4447
imports: [MatStepperModule, NoopAnimationsModule, ReactiveFormsModule],
@@ -53,7 +56,7 @@ describe('MatStepper', () => {
5356
LinearStepperWithValidOptionalStep,
5457
],
5558
providers: [
56-
{provide: Directionality, useFactory: () => ({value: dir})}
59+
{provide: Directionality, useFactory: () => dir}
5760
]
5861
});
5962

@@ -410,7 +413,7 @@ describe('MatStepper', () => {
410413
let fixture: ComponentFixture<SimpleMatVerticalStepperApp>;
411414

412415
beforeEach(() => {
413-
dir = 'rtl';
416+
dir.value = 'rtl';
414417
fixture = TestBed.createComponent(SimpleMatVerticalStepperApp);
415418
fixture.detectChanges();
416419
});
@@ -739,7 +742,7 @@ describe('MatStepper', () => {
739742
});
740743

741744
it('should reverse arrow key focus in RTL mode', () => {
742-
dir = 'rtl';
745+
dir.value = 'rtl';
743746
let fixture = TestBed.createComponent(SimpleMatVerticalStepperApp);
744747
fixture.detectChanges();
745748

@@ -766,13 +769,27 @@ describe('MatStepper', () => {
766769
});
767770

768771
it('should reverse arrow key focus in RTL mode', () => {
769-
dir = 'rtl';
772+
dir.value = 'rtl';
770773
let fixture = TestBed.createComponent(SimpleMatHorizontalStepperApp);
771774
fixture.detectChanges();
772775

773776
let stepHeaders = fixture.debugElement.queryAll(By.css('.mat-horizontal-stepper-header'));
774777
assertArrowKeyInteractionInRtl(fixture, stepHeaders);
775778
});
779+
780+
it('should reverse arrow key focus when switching into RTL after init', () => {
781+
let fixture = TestBed.createComponent(SimpleMatHorizontalStepperApp);
782+
fixture.detectChanges();
783+
784+
let stepHeaders = fixture.debugElement.queryAll(By.css('.mat-horizontal-stepper-header'));
785+
assertCorrectKeyboardInteraction(fixture, stepHeaders, 'horizontal');
786+
787+
dir.value = 'rtl';
788+
dir.change.emit('rtl');
789+
fixture.detectChanges();
790+
791+
assertArrowKeyInteractionInRtl(fixture, stepHeaders);
792+
});
776793
});
777794

778795
describe('valid step in linear stepper', () => {

0 commit comments

Comments
 (0)