【问题标题】:Angular passing API response to child componentAngular 将 API 响应传递给子组件
【发布时间】:2019-07-16 14:17:24
【问题描述】:

我有一个“Dashboard”组件和一个“Dashboard-InfoBox”子组件。 在我的 Dashboard 组件中,我在服务中调用一个返回 API 响应的函数,然后创建一个变量来保存我想要的数据并将其传递给 Dashboard-InfoBox 以呈现它。

问题是 Dashboard-infobox 尝试在数据还不存在时访问数据,这导致我的控制台出现错误。

我已经尝试包含 *ngIf="marketData['HENRYHUB']",但是当数据到来时 ngIf 没有呈现它。

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>

错误类型错误:无法读取未定义的属性“价格”

对于这些变量中的每一个,我在控制台中收到 4 个错误。然而,在我的仪表板上,一切都完全按照我想要的方式显示。

【问题讨论】:

  • 使用https://www.npmjs.com/package/a4-observable-cache免费获取缓存,而不是在所有可观察对象上实现自己的(和重复的代码)
  • 谢谢,这似乎是一个很好的解决方案。我会尝试使用它!

标签: angular typescript rest api


【解决方案1】:

在您的仪表板信息框组件模板中,使用 *ngIf 包装 div,就像您在编辑问题之前所做的那样。

另外,你应该只使用一个img 标签而不是两个。无论如何,您都是有条件地显示它们。

来,试试看:

<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>

【讨论】:

  • 感谢您的修改。当我为 HENRYHUB 做这件事时,这确实奏效了。但是,当我将所有 div 更改为与此类似时,没有呈现任何内容。我已经编辑了帖子以包含以上所有内容。
  • 另外:如果我用路由器导航到另一个链接,然后返回到仪表板,一切都会很好地呈现,并且准确地显示我想要的内容而没有错误。
  • 它应该可以正常工作。可以在父组件的subscribe 块中设置HENRYHUB 是原因吗?只是在说!如果没有,你介意为我创建一个最小的 StackBlitz 来复制这个问题吗?
  • 我做了一个stackblitz,效果很好。这是我见过的最奇怪的事情,有 5 个 div,每个都有一个 *ngIf,在 stackblitz 上它们工作得很好,并且每个在数据到来时都会显示。但是,当我为我的项目提供服务时,它不会显示任何内容,如果我在路由器中切换链接并返回,它会显示它们。更奇怪的是,如果我从 1 个 DIVS 中删除 1 *ngIf,它会起作用。但是我会在控制台中收到该 DIV 的错误。
【解决方案2】:

只需检查您的 ng-if 与您初始化为 {} 的 marketData 变量(不为空)

<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>

您有错误,因为当 Angular 首先检查变量是否为空时,changeDetection 会起作用并将值传递给您的孩子,所以一切都会呈现

【讨论】:

  • 你设置*ngIf的方式,我很确定它总是会导致true
猜你喜欢
  • 1970-01-01
  • 2018-11-25
  • 2019-06-10
  • 2018-10-05
  • 1970-01-01
  • 2017-10-11
  • 2019-10-31
  • 1970-01-01
  • 2017-08-30
相关资源
最近更新 更多