首页 > 解决方案 > 从 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/"}]}

我正在尝试使用插值来迭代模板中的名称。但由于“名称”包含在 api 的“结果”中,因此只有在模板中使用结果时才能访问它。这会产生一个错误,并且它通常不会因此而编译。

我的 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`);

  }

我的班级文件

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>

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

标签: angularapistring-interpolation

解决方案


您的错误是因为pokemon当您尝试做*ngFor正确的事情时为空?在这种情况下,您可以在 HTML 中添加?after 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.。这是因为 field species 不是一个数组而是一个对象,所以你必须使用keyvalue管道。单击此处获取文档


推荐阅读