0

I have a parent component that dynamically adds child components

@Component({
  selector: 'app-parent',
  template: `<p>Parent:</p><ng-container #dynamic></ng-container>`
})
export class ParentComponent implements OnInit {
  @ViewChild('dynamic', { read: ViewContainerRef }) vcr: ViewContainerRef;

  constructor(private fr: ComponentFactoryResolver) {
    
  }

  ngOnInit() {
    const factory = this.fr.resolveComponentFactory(HelloComponent);
    const ref = this.vcr.createComponent(factory);
    ref.instance.name = 'World';
  }

}

And the child component is as follows

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>`
})
export class HelloComponent {
  @Input() name: string;
}

When I change the value of name on click of a button (ref.instance.name='Bird') it doesn't update the child component view with the new value of name. I tried ref.changeDetectorRef.detectChanges() as well but even that doesn't update the child component view. I read articles online which said that changeDetectorRef.detectChanges() runs on the host view not on the component itself.
How do I update the child component view when the value of name variable changes?

K.Shikha
  • 107
  • 2
  • 14
  • If you are using @Input() in your child component, do you need @ViewChild in your parent ? Just pass the variable and change its context inside parent component, or use ngOnChanges() – godocmat Apr 22 '21 at 00:08

2 Answers2

1

View related manipulation should be done only inside or after ngAfterViewInit is called. I tried your sample and moved your code to ngAfterViewInit method and it started working.

@Component({
  selector: 'app-root',
  template: `<p>Parent:</p><ng-container #dynamic></ng-container>`,
  styleUrls: ['./app.component.less']
})
export class AppComponent implements AfterViewInit {
  title = 'dynamic-child';

  @ViewChild('dynamic', { read: ViewContainerRef }) vcr: ViewContainerRef;

  constructor(private fr: ComponentFactoryResolver) {
    
  }
  ngAfterViewInit(): void {
    const factory = this.fr.resolveComponentFactory(HelloComponent);
    const ref = this.vcr.createComponent(factory);
    ref.instance.name = 'World';
  }

}
Sunil Pandey
  • 7,042
  • 7
  • 35
  • 48
0

After you update inputs call ref.changeDetectorRef.detectChanges(); to trigger change detection

ngOnInit() {
    const factory = this.fr.resolveComponentFactory(HelloComponent);
    const ref = this.vcr.createComponent(factory);
    ref.instance.name = 'World';
    ref.changeDetectorRef.detectChanges();  
}
Vova Bilyachat
  • 18,765
  • 4
  • 55
  • 80