无法绑定到Rest服务返回的对象的属性

问题描述

这可能是一件很基本的事情,做错了,所以您将不得不原谅我的无知,但是我只是在学习Angular,遇到了一个非常烦人的障碍,我似乎无法找到与我的Google搜索相关的任何内容

我正在跟踪一个教程,该教程将获取一些静态JSON数据以收取运输费用,并将其绑定为一个运输组件。我有一个获取数据的服务,看起来像这样,但是我删除了与此问题无关的代码

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class CartService {

  constructor(
     private http: HttpClient
  ) { }

  getShippingPrices() {
    return this.http.get('/assets/shipping.json');
  }

}

运输组件代码如下:

import { Component,OnInit } from '@angular/core';
import { CartService } from '../cart.service';

@Component({
  selector: 'app-shipping',templateUrl: './shipping.component.html',styleUrls: ['./shipping.component.css']
})
export class ShippingComponent implements OnInit {

  constructor(
    private cartService: CartService
  ) { }

  shippingCosts;

  ngOnInit() {
        this.shippingCosts = this.cartService.getShippingPrices();
  }

}

这样的标记

<div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
  <span>{{ shipping.type }}</span>
  <span>{{ shipping.price | currency }}</span>
</div>

所有这些都适用于本教程中的示例数据,如下所示:

[
  {
    "type": "Overnight","price": 25.99
  },{
    "type": "2-Day","price": 9.99
  },{
    "type": "Postal","price": 2.99
  }
]

但是,我真正想做的是调用一个Web服务,该服务返回的数据更像这样:

{"shipping":[
  {
    "type": "Overnight","price": 2.99
  }
]}

当我上次在分裂之前使用Angular时,现在被称为angularjs,我认为我可以做这样的事情:

<div class="shipping-item" *ngFor="let shipping of shippingCosts.shipping | async">
  <span>{{ shipping.type }}</span>
  <span>{{ shipping.price | currency }}</span>
</div>

这似乎现在不起作用,它什么也没做,没有错误,没有在浏览器中呈现,没有ajax调用获取数据,没有任何我可以检测到的东西。

我还认为我可以回溯到史前时代,像这样:

  ngOnInit() {
    let temp = this.cartService.getShippingPrices();
    this.shippingCosts = temp.shipping;
  }

与尝试绑定到属性类似,这也没有做任何事情,没有错误,没有呈现任何内容,没有ajax调用获取数据。

所以我的问题是,我该如何绑定到深入到要返回的数据一级的数组。

解决方法

http请求是异步的。当您这样做

this.shippingCosts = this.cartService.getShippingPrices();

一个Observable存储在shippingCosts中,而不存储在您指定的数据中。您必须执行以下操作

this.cartService.getShippingPrices()
   .subscribe(costs => {
      this.shippingCosts = cost;
   });

我个人喜欢在这种情况下与学生们合作

this.cartService.getShippingPrices().toPromise()
   .then(costs => {
        this.shippingCosts = cost;
   })
   .catch(err => {
        console.log(err);
   });

您还可以将对服务的请求移至异步方法,然后像这样调用它

async loadShippingCart() {
   this.shippingCosts = await this.cartServices.getShippingPrices().toPromise();
}

然后从ngOnInit方法中调用它

希望这可以为您提供帮助

,

您的语法在这里是错误的:

<div class="shipping-item" *ngFor="let shipping of shippingCosts.shipping | async">
  <span>{{ shipping.type }}</span>
  <span>{{ shipping.price | currency }}</span>
</div>

应该是这样的:

<div class="shipping-item" *ngFor="let shipping of (shippingCosts | async)?.shipping">
  <span>{{ shipping?.type }}</span>
  <span>{{ shipping?.price | currency }}</span>
</div>

所以,事情首先是需要获得与此(shippingCosts | async)异步的可观察值,然后再从中获得所需的任何值,例如?.shipping

奖金提示:当对象属性为null,未定义等(例如?)时,请始终使用elvis运算符shipping来避免可能的应用崩溃