Angular 从 api 获取插值错误

Angular interpolation error fetching from api

这是一个项目。我需要从这个 api: https://pokeapi.co/ 访问一个数组。我能够访问数组,它看起来像这样:

{"count":1050,"next":"https://pokeapi.co/api/v2/pokemon?offset=20&limit=20","previous":null,"results":[{"name":"bulbasaur","url":"https://pokeapi.co/api/v2/pokemon/1/"},{"name":"ivysaur","url":"https://pokeapi.co/api/v2/pokemon/2/"},{"name":"venusaur","url":"https://pokeapi.co/api/v2/pokemon/3/"},{"name":"charmander","url":"https://pokeapi.co/api/v2/pokemon/4/"},{"name":"charmeleon","url":"https://pokeapi.co/api/v2/pokemon/5/"},{"name":"charizard","url":"https://pokeapi.co/api/v2/pokemon/6/"},{"name":"squirtle","url":"https://pokeapi.co/api/v2/pokemon/7/"},{"name":"wartortle","url":"https://pokeapi.co/api/v2/pokemon/8/"},{"name":"blastoise","url":"https://pokeapi.co/api/v2/pokemon/9/"},{"name":"caterpie","url":"https://pokeapi.co/api/v2/pokemon/10/"},{"name":"metapod","url":"https://pokeapi.co/api/v2/pokemon/11/"},{"name":"butterfree","url":"https://pokeapi.co/api/v2/pokemon/12/"},{"name":"weedle","url":"https://pokeapi.co/api/v2/pokemon/13/"},{"name":"kakuna","url":"https://pokeapi.co/api/v2/pokemon/14/"},{"name":"beedrill","url":"https://pokeapi.co/api/v2/pokemon/15/"},{"name":"pidgey","url":"https://pokeapi.co/api/v2/pokemon/16/"},{"name":"pidgeotto","url":"https://pokeapi.co/api/v2/pokemon/17/"},{"name":"pidgeot","url":"https://pokeapi.co/api/v2/pokemon/18/"},{"name":"rattata","url":"https://pokeapi.co/api/v2/pokemon/19/"},{"name":"raticate","url":"https://pokeapi.co/api/v2/pokemon/20/"}]}

我正在尝试使用插值来迭代模板中的名称。但由于 'name' 包裹在 api 上的 'results' 中,只有在模板中使用结果才能到达它。这会产生错误,结果通常不会编译。

我的ts文件

import { Component, OnInit } from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {PokemonData} from '../../models/pokemon';
import {PokemonService} from '../../models/services/pokemon.service';

@Component({
  selector: 'app-pokemon-data',
  templateUrl: './pokemon-data.component.html',
  styleUrls: ['./pokemon-data.component.css']
})
export class PokemonDataComponent implements OnInit {
  // @Input() id: string;
  public pokemonData: PokemonData[] = [];
  private name: string;

  constructor(private pokemonService: PokemonService, private route: ActivatedRoute) {
        this.name = this.route.snapshot.paramMap.get('name');
  }
    onLoadPokemonByName(): void {
    this.pokemonService.getPokemonbyName(this.name).subscribe(
      res => {
        console.log(this.name);
        this.pokemonData = JSON.parse(JSON.stringify(res));
        console.log(this.pokemonData);
      }
    );

  }
  ngOnInit(): void {
    this.onLoadPokemonByName();
  }

}

这是 html 文件

<p>pokemon works!</p>
<div *ngFor="let res of pokemon.results">
  <div>{{res.name}}, {{res.url}}</div>
  <button routerLink="/pokemondata/{{res.name}}">Pokemon Details</button>
</div>

这是服务文件

import { Injectable } from '@angular/core';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http';
import {Pokemon, PokemonData} from '../pokemon';

@Injectable({
  providedIn: 'root'
})
export class PokemonService {

  constructor(private http: HttpClient) {

  }

  // http call
  private baseUrl = 'https://pokeapi.co/api/v2/';

  getPokemonList(): Observable<Pokemon[]> {
    return this.http.get<Pokemon[]>(this.baseUrl + `pokemon?limit=150`);

  }

我的class文件

export class Pokemon {
  // this class contains properties that contain information on Pokemons
  name: string;
  url: string;
  results: Result[];

}

export interface Result {
  results: Result[];
}

我的问题:如何实例化结果以使 i5 不会在模板中导致错误。

额外的 ts 文件

import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog';
import {PokemonService} from '../../models/services/pokemon.service';
import {PokemonData} from '../../models/pokemon';
import {Chain, Evolution, Species} from '../../models/evolution';
import {ActivatedRoute} from '@angular/router';

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

evolution: Evolution;
species: Species;
chain: Chain;
private id: string;

  constructor(private pokemonService: PokemonService,
              private route: ActivatedRoute) {
    this.id = this.route.snapshot.paramMap.get('id');

  }

   getEvolutionDetails(): void {
    this.pokemonService.getEvolutionData(this.id).subscribe((
      res => {
        console.log(this.id);
        this.evolution = JSON.parse(JSON.stringify(res));
        console.log(this.evolution);
      }
    ));

   }
  ngOnInit(): void {
    this.getEvolutionDetails();
  }

}

html 文件

  <p *ngIf="evolution.chain.species">
  <div *ngFor="let res of evolution.chain.species">{{res.name}} </div>

我得到的错误: 无法读取未定义的 属性 'chain' 和 vendor.js:77062 错误错误:找不到类型为 'bulbasaur' 的不同支持对象“[object Object]”。 NgFor 仅支持绑定到 Iterables,例如 Arrays。

您的错误是因为当您尝试执行 *ngForpokemon 为空?在这种情况下,您可以在 HTML.

中的 pokemon 之后添加 ?
<div *ngFor="let res of pokemon?.results">
  <div>{{res.name}}, {{res.url}}</div>
  <button routerLink="/pokemondata/{{res.name}}">Pokemon Details</button>
</div>

为了确保您有结果,最好在 res 之后添加 ?

<div *ngFor="let res of pokemon?.results">
  <div>{{res?.name}}, {{res?.url}}</div>
  <button routerLink="/pokemondata/{{res?.name}}">Pokemon Details</button>
</div>

或者你可以做一个 if

<ng-container *ngIf="pokemon">
  <div *ngFor="let res of pokemon?.results">
    <div>{{res?.name}}, {{res?.url}}</div>
    <button routerLink="/pokemondata/{{res?.name}}">Pokemon Details</button>
  </div>
</ng-container>

对于你的 EvolutionComponent 的第二个错误,你有 2 个错误:

  <p *ngIf="evolution.chain.species">
  <div *ngFor="let res of evolution.chain.species">{{res.name}} </div>

要修复它们,您可以这样做:

  <p *ngIf="evolution?.chain?.species">
  <div *ngFor="let res of evolution?.chain?.species | keyvalue">{{res?.value?.name}} </div>

?是检查值是否不为空

对于错误NgFor only supports binding to Iterables such as Arrays.。这是因为字段 species 不是数组而是对象,因此您必须使用 keyvalue 管道。单击 here 获取文档