There is a parent component with default changeDetection and two child components with onPush change detection strategy. While the input variable is being updated, the template will not update. I can't used async pipes in the ChildBComponent as it is a global UI component for the project and refactoring is not an option. How do I go about this?
parent.ts
@Component({
selector: 'parent',
template: `
<div>
<child-a>
<child-b [label]="firstLabel"></child-b>
<child-b [label]="secondLabel"></child-b>
<child-b label="Just a plain label"></child-b>
</child-a>
</div>`
})
export class ParentComponent implements OnInit {
public ngOnInit(): void {
this.httpService.loadData()
.subscribe(data => {
this.someValue = 1;
this.otherValue = 2;
});
}
// getters to explicitly trigger change detection
public get firstLabel(): string {
return `Something ${ this.someValue || '?'}`;
}
public get secondLabel(): string {
return `Different ${ this.otherValue || '?'}`;
}
}
child-a.ts
@Component({
selector: 'child-a',
template: `
<div>Layout wrapper</div>
<ng-content></ng-content>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterContentInit {
}
child-b.ts
@Component({
selector: 'child-b',
template: '<div>{{ label }}</div>',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterViewInit, OnDestroy {
@Input public label: string;
}
I tried converting @Input into getter/setter - to no avail. When debugging, the changes are coming through, but the template will only update if I click on the component itself. Throwing in a markForCheck() didn't help either.
And idea is helpful.
Edit: Added StackBlitz. Please use a wide preview to see the issue; miraculously it works properly when mobile view elements are shown.
loadData.subscribe?