How to update a value in the dynamically added child component in Angular 9

1.9k views Asked by At

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?

2

There are 2 answers

0
Vova Bilyachat On

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();  
}
0
Sunil Pandey On

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';
  }

}