Arianule
Arianule

Reputation: 9043

ViewChild component undefined when trying to call method

I am retrieving data from a db and data is ready I am trying to bind to a child element by using ViewChild so as to pass obj data to the child element

The issue is that the component is not "ready" so I set a timeout of 2 seconds.

This doesn't feel right. How would I know if the child component is ready.

Parent component retrieves data from the DB

 @ViewChild("assumps") assumps: AssumptionsComponent
 getProposalAmounts() {
    this.targets.getProposalAmounts().subscribe((data) => {
    this.assumptions = data.assumptions;

    setTimeout(() => {
      this.assumps.setAssumptionsForm(this.assumptions);
    }, 2000)

Inside the child component

setAssumptionsForm(obj: Assumptions) {
if (obj != null) {
  this.assumptionsObj = obj;
}

Without the timeout the child in null; Error reads Cannot read property 'setAssumptionsForm' of undefined

Thank you

Upvotes: 2

Views: 1509

Answers (2)

Pankaj Parkar
Pankaj Parkar

Reputation: 136134

It seems like you're expecting to render assumps template as soon as you assign this.assumptions value, and expecting to render that DOM instantly. But it doesn't happen in that way. Correct me if my assumptions are wrong.

Rather you can consider creating QueryList(special Observable) of AssumptionsComponent when you did ViewChild query. And later you can keep eye on QueryList Observable changes property. Thereafter you can directly get the changes(DOM removal and addition) happening over #assumps template variable.

@ViewChild("assumps") assumps: QueryList<AssumptionsComponent>;


getProposalAmounts() {
    this.targets.getProposalAmounts().subscribe((data) => {
    this.assumptions = data.assumptions;
}

ngOnInit () {
    this.assumps.changes((list) => {
        list.forEach(assump => 
          assump.setAssumptionsForm(this.assumptions)
        )
    })        
}

Upvotes: 1

Nathan Gavenski
Nathan Gavenski

Reputation: 263

You could create a service for your component and subscribe to it. When you child constructor is executed you emit an event for your service letting the parent know that he is ready.

That seems to me the best solution.

Another way is to pass your data as input for your child component and create a loader for when your data is missing.

I actually prefere the first one, since it is a more reusable approach :)

Upvotes: 1

Related Questions