0

I have two child components included in my parent component. Depending on a selection I am rendering one of them. This looks as follows in my html (the ngIf):

<app-default-child *ngIf="selectedExperiment && selectedExperiment.projectType === 'default'" (newFormEvent)="onExperimentOptionsFormChange($event)"></app-default-child>
<app-scenario-child *ngIf="selectedExperiment && selectedExperiment.projectType === 'scenario'" (newFormEvent)="onExperimentOptionsFormChange($event)"></app-scenario-child>

Now I want to call a function of one of the components inside of my ngOnInit() but my ViewChild is undefined.

export class myComponent implements OnInit, OnDestroy {
  @ViewChild(DefaultChildComponent) defaultChild:DefaultChildComponent
  @ViewChild(ScenarioChildComponent) scenarioChild:ScenarioChildComponent
  selectedExperiment: Experiment

  ngOnInit(){
    this.doSomething();
  }

  doSomething(){
    this.selectedExperiment = exp //I am getting this in elsewhere
  
    // Here I am getting the undefined now, no matter which child
    if(this.selectedExperiment.projectType === ProjectType.Default){
      this.defaultChild.doSomething();
    } else if (this.selectedExperiment.projectType === ProjectType.Scenario) {
      this.scenarioChild.doSomething();
    }
  }
}
lasJac
  • 39
  • 6
  • 3
    have you tried using the ngAfterViewInit lifecycle instead of ngoninit? also check this answer because you're using ngif on what would be the viewchild https://stackoverflow.com/questions/39366981/viewchild-in-ngif – Dream_Cap Oct 17 '22 at 00:31

1 Answers1

0

As per your code major issue is that you are making this.selectedExperiment.projectType value initialized within the same block you are trying to call doSomething().

So when this.selectedExperiment.projectType is initialized to a default value it would not immediately render components.

What you can do is you can use setter method with @Viewchild as follows

  // having this is not a must, if you want for further development have this
  private defaultChildRef: DefaultChildComponent;
  private scenarioChildRef: ScenarioChildComponent;


  @ViewChild(DefaultChildComponent) set defaultChild(defaultChild: DefaultChildComponent) {
    if(defaultChild) { // initially setter gets called with undefined
        defaultChild.doSomething();
        this.defaultChildRef = defaultChild;
    }
  }

  @ViewChild(ScenarioChildComponent) set scenarioChild(scenarioChild: ScenarioChildComponent) {
    if(scenarioChild) { // initially setter gets called with undefined
        scenarioChild.doSomething();
        this.scenarioChildRef = scenarioChild;
    }
  }

Within your doSomething() method in parent component you can simply initialize selectedExperiment. No need to call child component functions here.

  doSomething(exp: Experiment) {
    this.selectedExperiment = exp; 
  }

Here is a sample StackBlitz containing the codes

Kelum Bandara
  • 443
  • 4
  • 9