AgedPeanuts
AgedPeanuts

Reputation: 145

Angular passing API response to child component

I have a "Dashboard" component, and a "Dashboard-InfoBox" child component. In my Dashboard component I call a function in my service that returns the API response, and then I create a variable that holds the data that I want and pass it to Dashboard-InfoBox to render it.

The problem is that Dashboard-infobox tries to access the data while it's still not there, which causes errors in my console.

I have tried including *ngIf="marketData['HENRYHUB']", but the ngIf is not rendering it when the data comes.

market.service.ts


  getHenryHub() {
    const henryHubCache = this.responseCache.get(this.henryHubURL);
    if(henryHubCache) {
      console.log(henryHubCache);
      return of(henryHubCache);
    }
    const response = this.http.get<EiaResponse>(this.henryHubURL);
    response.subscribe(res => this.responseCache.set(this.henryHubURL, res));
    return response;
  }

dashboard.component.ts

this.marketData = {} as IDictionary;

    this.marketDataService.getHenryHub().subscribe(res => {
      let henryHub = {
        date: res["series"][0].data[0][0],
        price: res["series"][0].data[0][1].toFixed(2),
        status: res["series"][0].data[0][1] > res["series"][0].data[1][1] ? true : false,
      }
    this.marketData['HENRYHUB'] = henryHub;
    });

dashboard-infobox.component.ts

  @Input() marketData: any;

        <div *ngIf="marketData" class="tab-wrapper" style="float: right">
    <div class="exchange" style="border-bottom: 1px solid #1e6ec8;">
        <p style="font-weight: 600; margin: auto;">
            Gas/Oil Prices
        </p>
    </div>

    <div class="exchange" *ngIf="marketData.BRENT">
        <p style="flex: 0 0 30%; margin-left: 15px;">
            Brent Oil
        </p>
        <img matListAvatar [src]="marketData.BRENT.status ? 'assets/img/up.png' : 'assets/img/down.png'" style="width: 20px" />
        <p style="flex: 0 0 40%; margin-left: 15px;">
            {{ marketData.BRENT.price }} $/Bbl
        </p>
        <p>
            {{ date | date: 'MMM dd' }}
        </p>
    </div>

    <div class="exchange" *ngIf="marketData.HENRYHUB">
        <p style="flex: 0 0 30%; margin-left: 15px;">
            Henry Hub
        </p>
        <img matListAvatar [src]="marketData.HENRYHUB.status ? 'assets/img/up.png' : 'assets/img/down.png'" style="width: 20px" />
        <p style="flex: 0 0 40%; margin-left: 15px;">
            {{ marketData.HENRYHUB.price }} $/MMBtu
        </p>
        <p>
            {{ date | date: 'MMM dd' }}
        </p>
    </div>

    <div class="exchange" *ngIf="marketData.NBP">
        <p style="flex: 0 0 30%; margin-left: 15px;">
            NBP
        </p>
        <img matListAvatar [src]="marketData.NBP.status ? 'assets/img/up.png' : 'assets/img/down.png'" style="width: 20px" />
        <p style="flex: 0 0 40%; margin-left: 15px;">
            {{ marketData.NBP.price }} $/MMBtu
        </p>
        <p>
            {{ date | date: 'MMM dd' }}
        </p>
    </div>

    <div class="exchange" *ngIf="marketData.TTF">
        <p style="flex: 0 0 30%; margin-left: 15px;">
            TTF
        </p>
        <img matListAvatar [src]="marketData.TTF.status ? 'assets/img/up.png' : 'assets/img/down.png'" style="width: 20px" />
        <p style="flex: 0 0 40%; margin-left: 15px;">
            {{ marketData.TTF.price }} $/MMBtu
        </p>
        <p>
            {{ date | date: 'MMM dd' }}
        </p>
    </div>

    <div class="exchange" *ngIf="marketData.GASOIL">
        <p style="flex: 0 0 30%; margin-left: 15px;">
            Gas Oil
        </p>
        <img matListAvatar [src]="marketData.GASOIL.status ? 'assets/img/up.png' : 'assets/img/down.png'" style="width: 20px" />
        <p style="flex: 0 0 40%; margin-left: 15px;">
            {{ marketData.GASOIL.price }} $/Mt
        </p>
        <p>
            {{ date | date: 'MMM dd' }}
        </p>
    </div>
</div>

ERROR TypeError: Cannot read property 'price' of undefined

I get 4 errors in the console for each of these variables. However on my Dashboard everything shows exactly the way I want it.

Upvotes: 1

Views: 1171

Answers (2)

Robert garcia
Robert garcia

Reputation: 591

Just check your ng-if against the marketData variable which you initialized as {} (thats not null)

<div class="exchange" *ngIf="markedData && marketData !== {}">
      <p style="flex: 0 0 30%; margin-left: 15px;">
          Henry Hub
      </p>
      <img *ngIf="marketData['HENRYHUB'].status" matListAvatar 
        [src]="'assets/img/up.png'" 
        style="width: 20px"
        />
      <img *ngIf="!marketData['HENRYHUB'].status" matListAvatar 
        [src]="'assets/img/down.png'" 
        style="width: 20px"
        />
      <p style="flex: 0 0 40%; margin-left: 15px;">
      {{ marketData['HENRYHUB'].price }} $/MMBtu
      </p>
      <p>
      {{ date | date: 'MMM dd' }}
      </p>
    </div>

You have errors because when Angular firsts checks the variable is null, then the changeDetection works and pass the value to your child, so everything renders

Upvotes: 0

SiddAjmera
SiddAjmera

Reputation: 39452

In your dashboard-infobox Component Template, wrap the div with an *ngIf the way you were doing before you edited the question.

Plus, you should be good with just one img tag instead of two. You're showing them conditionally anyway.

Here, give this a try:

<div class="exchange" *ngIf="marketData.HENRYHUB">
  <p style="flex: 0 0 30%; margin-left: 15px;">
    Henry Hub
  </p>
  <img 
    matListAvatar 
    [src]="marketData.HENRYHUB.status ? 'assets/img/up.png' : 'assets/img/down.png'" 
    style="width: 20px" />
  <p style="flex: 0 0 40%; margin-left: 15px;">
    {{ marketData.HENRYHUB.price }} $/MMBtu
  </p>
  <p>
    {{ date | date: 'MMM dd' }}
  </p>
</div>

Upvotes: 1

Related Questions