https://stackblitz.com/edit/angular-xpamld
Question: Can someone help me understand why my prototype's changeDetection: ChangeDetectionStrategy.OnPush
still allows me to update the inner value name
? If this is not what ChangeDetectionStrategy.OnPush
suppose to prevent, what should it be doing?
app.component.ts:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
public name = 'Angular 5';
public changeName() {
this.name = 'Outer';
}
}
app.component.html:
<hello name="{{ name }}"></hello>
<button (click)="changeName()">Outter Change</button>
<p>{{name}}-- outer</p>
<p>
Start editing to see some magic happen :)
</p>
hello.component.ts:
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1> <button (click)="changeName()">inner Change</button>`,
styles: [`h1 { font-family: Lato; }`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent {
@Input() name: string;
public changeName() {
this.name = 'Inner';
}
}
Because primitive datatype is immutable - if you change it, its reference also changes, so ChangeDetectorRef
of your component knows it must detect changes (because OnPush
looks for references changes, not data mutations in arrays, objects). If you want to avoid that on primitives, you can manually deactivate/activate this on ChangeDetectorRef instance with detach()
/ reattach()
:
import { ChangeDetectorRef } from '@angular/core';
export class HelloComponent {
@Input() name: string;
constructor(private ref: ChangeDetectorRef) {}
public changeName() {
this.ref.detach();
this.name = 'Inner';
}
}