Using Angular 4.3 and the following Plunkr.
Please consider the following components:
@Component({
selector: 'my-app',
template: `
<div>
<button type="button" (click)="toggle()">Toggle</button>
<div #anchor></div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class App {
@ViewChild('anchor', {read: ViewContainerRef}) anchor: ViewContainerRef;
dynamicRef: ComponentRef;
value = true;
constructor(private cfr: ComponentFactoryResolver, private cdr: ChangeDetectorRef) {}
ngAfterViewInit(): void {
let factory = this.cfr.resolveComponentFactory(Dynamic);
this.dynamicRef = this.anchor.createComponent(factory);
this.dynamicRef.instance.value = this.value;
this.dynamicRef.changeDetectorRef.detectChanges();
}
toggle(): void {
this.value = !this.value;
this.dynamicRef.instance.value = this.value;
this.dynamicRef.changeDetectorRef.detectChanges();
}
}
@Component({
template: `Value: {{value}}`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Dynamic {
@Input() value = true;
}
The App component creates the Dynamic component using the standard ComponentFactoryResolver + ViewContainerRef strategy. Both components have an OnPush change detection strategy. When the App.toggle() method is called, it toggles App.value, propagates this new value to Dynamic.value and forces a change detection run on the dynamic component's change detector. I expect the correct value to be displayed by the dynamic component's template, but it actually never changes. Switching both components to the Default change detection strategy provides the expected behaviour.
Why isn't the dynamic component template re-rendered properly and how can this be fixed?