Skip to content

Commit 9d632f7

Browse files
committed
fix(stepper): switch to OnPush change detection
* Adds OnPush change detection to all stepper-related components. * Enables the tslint rule that requires OnPush for all components.
1 parent 3c6f7a2 commit 9d632f7

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ import {
2424
ViewEncapsulation,
2525
Optional,
2626
Inject,
27-
forwardRef
27+
forwardRef,
28+
ChangeDetectionStrategy,
29+
ChangeDetectorRef,
30+
OnChanges,
2831
} from '@angular/core';
2932
import {LEFT_ARROW, RIGHT_ARROW, ENTER, SPACE} from '@angular/cdk/keycodes';
3033
import {CdkStepLabel} from './step-label';
@@ -62,8 +65,9 @@ export class StepperSelectionEvent {
6265
templateUrl: 'step.html',
6366
encapsulation: ViewEncapsulation.None,
6467
preserveWhitespaces: false,
68+
changeDetection: ChangeDetectionStrategy.OnPush,
6569
})
66-
export class CdkStep {
70+
export class CdkStep implements OnChanges {
6771
/** Template for step label if it exists. */
6872
@ContentChild(CdkStepLabel) stepLabel: CdkStepLabel;
6973

@@ -73,12 +77,11 @@ export class CdkStep {
7377
/** The top level abstract control of the step. */
7478
@Input() stepControl: AbstractControl;
7579

76-
/** Whether user has seen the expanded step content or not . */
80+
/** Whether user has seen the expanded step content or not. */
7781
interacted = false;
7882

7983
/** Label of the step. */
80-
@Input()
81-
label: string;
84+
@Input() label: string;
8285

8386
@Input()
8487
get editable() { return this._editable; }
@@ -115,6 +118,12 @@ export class CdkStep {
115118
select(): void {
116119
this._stepper.selected = this;
117120
}
121+
122+
ngOnChanges() {
123+
// Since basically all inputs of the MdStep get proxied through the view down to the
124+
// underlying MdStepHeader, we have to make sure that change detection runs correctly.
125+
this._stepper._stateChanged();
126+
}
118127
}
119128

120129
@Directive({
@@ -164,7 +173,9 @@ export class CdkStepper {
164173
/** Used to track unique ID for each stepper component. */
165174
_groupId: number;
166175

167-
constructor(@Optional() private _dir: Directionality) {
176+
constructor(
177+
@Optional() private _dir: Directionality,
178+
private _changeDetectorRef: ChangeDetectorRef) {
168179
this._groupId = nextId++;
169180
}
170181

@@ -188,6 +199,11 @@ export class CdkStepper {
188199
return `mat-step-content-${this._groupId}-${i}`;
189200
}
190201

202+
/** Marks the component to be change detected. */
203+
_stateChanged() {
204+
this._changeDetectorRef.markForCheck();
205+
}
206+
191207
/** Returns position state of the step with the given index. */
192208
_getAnimationDirection(index: number): StepContentPositionState {
193209
const position = index - this._selectedIndex;
@@ -218,6 +234,7 @@ export class CdkStepper {
218234
previouslySelectedStep: stepsArray[this._selectedIndex],
219235
});
220236
this._selectedIndex = newIndex;
237+
this._stateChanged();
221238
}
222239

223240
_onKeydown(event: KeyboardEvent) {

src/lib/dialog/dialog-container.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
ChangeDetectorRef,
1818
ViewChild,
1919
ViewEncapsulation,
20+
ChangeDetectionStrategy,
2021
} from '@angular/core';
2122
import {animate, AnimationEvent, state, style, transition, trigger} from '@angular/animations';
2223
import {DOCUMENT} from '@angular/platform-browser';
@@ -51,6 +52,9 @@ export function throwMatDialogContentAlreadyAttachedError() {
5152
styleUrls: ['dialog.css'],
5253
encapsulation: ViewEncapsulation.None,
5354
preserveWhitespaces: false,
55+
// Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.
56+
// tslint:disable-next-line:validate-decorators
57+
changeDetection: ChangeDetectionStrategy.Default,
5458
animations: [
5559
trigger('slideDialog', [
5660
// Note: The `enter` animation doesn't transition to something like `translate3d(0, 0, 0)

src/lib/stepper/step-header.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@
88

99
import {FocusMonitor} from '@angular/cdk/a11y';
1010
import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
11-
import {Component, Input, ViewEncapsulation, ElementRef, OnDestroy, Renderer2} from '@angular/core';
11+
import {
12+
Component,
13+
Input,
14+
ViewEncapsulation,
15+
ElementRef,
16+
OnDestroy,
17+
Renderer2,
18+
ChangeDetectionStrategy,
19+
} from '@angular/core';
1220
import {MatStepLabel} from './step-label';
1321

1422

@@ -23,6 +31,7 @@ import {MatStepLabel} from './step-label';
2331
},
2432
encapsulation: ViewEncapsulation.None,
2533
preserveWhitespaces: false,
34+
changeDetection: ChangeDetectionStrategy.OnPush,
2635
})
2736
export class MatStepHeader implements OnDestroy {
2837
/** Icon for the given step. */

src/lib/stepper/stepper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
SkipSelf,
2222
ViewChildren,
2323
ViewEncapsulation,
24+
ChangeDetectionStrategy,
2425
} from '@angular/core';
2526
import {FormControl, FormGroupDirective, NgForm} from '@angular/forms';
2627
import {
@@ -43,6 +44,7 @@ export const _MatStepper = CdkStepper;
4344
providers: [{provide: MAT_ERROR_GLOBAL_OPTIONS, useExisting: MatStep}],
4445
encapsulation: ViewEncapsulation.None,
4546
preserveWhitespaces: false,
47+
changeDetection: ChangeDetectionStrategy.OnPush,
4648
})
4749
export class MatStep extends _MatStep implements ErrorOptions {
4850
/** Content for step label given by <ng-template matStepLabel>. */
@@ -107,6 +109,7 @@ export class MatStepper extends _MatStepper {
107109
providers: [{provide: MatStepper, useExisting: MatHorizontalStepper}],
108110
encapsulation: ViewEncapsulation.None,
109111
preserveWhitespaces: false,
112+
changeDetection: ChangeDetectionStrategy.OnPush,
110113
})
111114
export class MatHorizontalStepper extends MatStepper { }
112115

@@ -131,5 +134,6 @@ export class MatHorizontalStepper extends MatStepper { }
131134
providers: [{provide: MatStepper, useExisting: MatVerticalStepper}],
132135
encapsulation: ViewEncapsulation.None,
133136
preserveWhitespaces: false,
137+
changeDetection: ChangeDetectionStrategy.OnPush,
134138
})
135139
export class MatVerticalStepper extends MatStepper { }

tslint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@
9191
"Component": {
9292
"encapsulation": "\\.None$",
9393
"moduleId": "^module\\.id$",
94-
"preserveWhitespaces": "false$"
94+
"preserveWhitespaces": "false$",
95+
"changeDetection": "\\.OnPush$"
9596
}
9697
}, "src/+(lib|cdk)/**/!(*.spec).ts"],
9798
"require-license-banner": [

0 commit comments

Comments
 (0)