Skip to content

Commit 5dc1893

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 df808b8 commit 5dc1893

File tree

5 files changed

+39
-12
lines changed

5 files changed

+39
-12
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 24 additions & 7 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';
@@ -60,9 +63,10 @@ export class StepperSelectionEvent {
6063
moduleId: module.id,
6164
selector: 'cdk-step',
6265
templateUrl: 'step.html',
63-
encapsulation: ViewEncapsulation.None
66+
encapsulation: ViewEncapsulation.None,
67+
changeDetection: ChangeDetectionStrategy.OnPush,
6468
})
65-
export class CdkStep {
69+
export class CdkStep implements OnChanges {
6670
/** Template for step label if it exists. */
6771
@ContentChild(CdkStepLabel) stepLabel: CdkStepLabel;
6872

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

75-
/** Whether user has seen the expanded step content or not . */
79+
/** Whether user has seen the expanded step content or not. */
7680
interacted = false;
7781

7882
/** Label of the step. */
79-
@Input()
80-
label: string;
83+
@Input() label: string;
8184

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

119128
@Directive({
@@ -163,7 +172,9 @@ export class CdkStepper {
163172
/** Used to track unique ID for each stepper component. */
164173
_groupId: number;
165174

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

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

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

222239
_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';
@@ -50,6 +51,9 @@ export function throwMdDialogContentAlreadyAttachedError() {
5051
templateUrl: 'dialog-container.html',
5152
styleUrls: ['dialog.css'],
5253
encapsulation: ViewEncapsulation.None,
54+
// Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.
55+
// tslint:disable-next-line:validate-decorators
56+
changeDetection: ChangeDetectionStrategy.Default,
5357
animations: [
5458
trigger('slideDialog', [
5559
// Note: The `enter` animation doesn't transition to something like `translate3d(0, 0, 0)

src/lib/stepper/step-header.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
10-
import {Component, Input, ViewEncapsulation} from '@angular/core';
10+
import {Component, Input, ViewEncapsulation, ChangeDetectionStrategy} from '@angular/core';
1111
import {MATERIAL_COMPATIBILITY_MODE} from '@angular/material/core';
1212
import {MdStepLabel} from './step-label';
1313

@@ -22,6 +22,7 @@ import {MdStepLabel} from './step-label';
2222
'role': 'tab',
2323
},
2424
encapsulation: ViewEncapsulation.None,
25+
changeDetection: ChangeDetectionStrategy.OnPush,
2526
providers: [{provide: MATERIAL_COMPATIBILITY_MODE, useValue: false}],
2627
})
2728
export class MdStepHeader {

src/lib/stepper/stepper.ts

Lines changed: 7 additions & 3 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 {
@@ -41,7 +42,8 @@ export const _MdStepper = CdkStepper;
4142
selector: 'md-step, mat-step',
4243
templateUrl: 'step.html',
4344
providers: [{provide: MD_ERROR_GLOBAL_OPTIONS, useExisting: MdStep}],
44-
encapsulation: ViewEncapsulation.None
45+
encapsulation: ViewEncapsulation.None,
46+
changeDetection: ChangeDetectionStrategy.OnPush,
4547
})
4648
export class MdStep extends _MdStep implements ErrorOptions {
4749
/** Content for step label given by <ng-template matStepLabel> or <ng-template mdStepLabel>. */
@@ -104,7 +106,8 @@ export class MdStepper extends _MdStepper {
104106
])
105107
],
106108
providers: [{provide: MdStepper, useExisting: MdHorizontalStepper}],
107-
encapsulation: ViewEncapsulation.None
109+
encapsulation: ViewEncapsulation.None,
110+
changeDetection: ChangeDetectionStrategy.OnPush,
108111
})
109112
export class MdHorizontalStepper extends MdStepper { }
110113

@@ -127,6 +130,7 @@ export class MdHorizontalStepper extends MdStepper { }
127130
])
128131
],
129132
providers: [{provide: MdStepper, useExisting: MdVerticalStepper}],
130-
encapsulation: ViewEncapsulation.None
133+
encapsulation: ViewEncapsulation.None,
134+
changeDetection: ChangeDetectionStrategy.OnPush,
131135
})
132136
export class MdVerticalStepper extends MdStepper { }

tslint.json

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

0 commit comments

Comments
 (0)