Update
The component with the OnPush strategy gets "modified detected" when their change input, EVEN IF their change detector is disconnected.
Since Angular 4.1.1 (2017-05-04) OnPush
must respect detach()
https://github.com/angular/angular/commit/acf83b9
Old version
There are many undocumented materials on how change detection works.
We need to know about the three main states of changeDetection ( cdMode
):
1) CheckOnce - 0
CheckedOnce
means that after calling detectChanges, the change detector mode will become Checked
.
Class appview
detectChanges(throwOnChange: boolean): void { ... this.detectChangesInternal(throwOnChange); if (this.cdMode === ChangeDetectorStatus.CheckOnce) { this.cdMode = ChangeDetectorStatus.Checked;
2) Verified - 1
Checked
means that the change detector should be skipped until its mode changes to CheckOnce
.
3) Separately - 3
Detached
means that the auxiliary tree of the change detector is not part of the main tree and should be skipped.
Here are the places where Detached
used
Class appview
Skip content check
detectContentChildrenChanges(throwOnChange: boolean) { for (var i = 0; i < this.contentChildren.length; ++i) { var child = this.contentChildren[i]; if (child.cdMode === ChangeDetectorStatus.Detached) continue;
Prospectus Verification
detectViewChildrenChanges(throwOnChange: boolean) { for (var i = 0; i < this.viewChildren.length; ++i) { var child = this.viewChildren[i]; if (child.cdMode === ChangeDetectorStatus.Detached) continue;
Skip cdMode
change to CheckOnce
markPathToRootAsCheckOnce(): void { let c: AppView<any> = this; while (isPresent(c) && c.cdMode !== ChangeDetectorStatus.Detached) { // <== this line if (c.cdMode === ChangeDetectorStatus.Checked) { c.cdMode = ChangeDetectorStatus.CheckOnce; } let parentEl = c.type === ViewType.COMPONENT ? c.declarationAppElement : c.viewContainerElement; c = isPresent(parentEl) ? parentEl.parentView : null; } }
Note: markPathToRootAsCheckOnce
works in all event handlers of your view:
So, if the Detached
state is set, your view will not be changed.
Then, how does OnPush
strategy work OnPush
OnPush
means that the change detector mode will be set to CheckOnce
during hydration.
compiler / src / view _compiler / property_binder.ts
const directiveDetectChangesStmt = isOnPushComp ? new o.IfStmt(directiveDetectChangesExpr, [compileElement.appElement.prop('componentView') .callMethod('markAsCheckOnce', []) .toStmt()]) : directiveDetectChangesExpr.toStmt();
https://github.com/angular/angular/blob/2.1.2/modules/%40angular/compiler/src/view_compiler/property_binder.ts#L193-L197
See how it looks in your example:
Parent factory (AppComponent)
And again, back to the AppView class :
markAsCheckOnce(): void { this.cdMode = ChangeDetectorStatus.CheckOnce; }
Scenario 1
1) Disable the OnPush children and children changes detector by default (click "detach ()" on both components)
OnPush.cdMode - Detached
3) Click "Edit Object" to pass the changed attribute to the children
AppComponent.detectChanges || \/ //if (self._OnPush_35_4.detectChangesInInputProps(self,self._el_35,throwOnChange)) { // self._appEl_35.componentView.markAsCheckOnce(); //} OnPush.markAsCheckOnce || \/ OnPush.cdMode - CheckOnce || \/ OnPush.detectChanges || \/ OnPush.cdMode - Checked
Therefore, OnPush.dectectChanges
triggered.
Here is the conclusion:
The OnPush
strategy component gets “modified detected” when their input changes, EVEN IF their change detector is disconnected. Moreover, it changes the viewing status to CheckOnce
.
Scenario2
1) Unplug the CD for the OnPush component
OnPush.cdMode - Detached
6) Click “Modify Object” to pass the changed attribute to children
See 3) from scenario 1 => OnPush.cdMode - Checked
7) For the last time, edit the internal input of the value and click the change button internal: a change is detected, and the internal value is updated ...
As I mentioned above, all event handlers include markPathToRootAsCheckOnce
. So:
markPathToRootAsCheckOnce || \/ OnPush.cdMode - CheckOnce || \/ OnPush.detectChanges || \/ OnPush.cdMode - Checked
As you can see, the OnPush strategy and ChangeDetector control one property - cdMode
The OnPush strategy component gets its change detector attached every time its input changes ...
In conclusion, I want to say that you are right.