ANGULAR - ngFor creating cards out of order when consuming Pokeapi api

Viewed 61

I'm finishing my pokedex and one of the things that's been bothering me is the fact that the cards that angular creates with ngFor are coming out of order. I'm just starting to use Angular and I wanted some help with this.

demo - https://pokedex-jrsbaum.vercel.app

HTML

<div class="container">
 <div class="row">
   <div class="col-md-4 ml-2 mt-2"
    *ngFor="let pokemon of pokemons" >
     <div class="card-container">
       <div class="card">
         <div
           class="front"
           [ngStyle]="{
             'background-color': getColors(pokemon.types[0]?.type.name)
           }"
         >

TS

import { Component, OnInit } from '@angular/core';
import { PokemonService } from 'src/app/services/pokemon.service';

@Component({
  selector: 'app-pokemon-list',
  templateUrl: './pokemon-list.component.html',
  styleUrls: ['./pokemon-list.component.css'],
})
export class PokemonListComponent implements OnInit {
  pokemons: any[] = [];
  species: any[] = [];

  constructor(public pokemonService: PokemonService) {}

  ngOnInit(): void {
    this.pokemonService.getPokemons().subscribe((response: any) => {
      response.results.forEach((result: { name: string }) => {
        this.pokemonService
          .getDetails(result.name)
          .subscribe((uniqResponse: any) => {
            this.pokemons.push(uniqResponse);
          });
        this.pokemonService
          .getSpecies(result.name)
          .subscribe((uniqResponse: any) => {
            this.species.push(uniqResponse);
          });
      });
    });
  }
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class PokemonService {
  constructor(private http: HttpClient) {}

  //Get Pokemons
  getPokemons() {
    return this.http.get(`https://pokeapi.co/api/v2/pokemon?limit=151`);
  }

  //Get More Pokemon Data
  getDetails(name: string) {
    return this.http.get(`https://pokeapi.co/api/v2/pokemon/${name}`);
  }

  getSpecies(name: string) {
    return this.http.get(`https://pokeapi.co/api/v2/pokemon-species/${name}/`);
  }
}

What I think is happening is that ngFor is making the call and stacking the cards, and the ones that are ready it releases before.

1 Answers

*ngFor orders array elements based on array indices. In your code, values pushed into pokemons array are fetched from some service call, which returns results asynchronously. This explains the random ordering.

To solve this, one solution is to use the array indices when inserting values into pokemons array.

Replace

this.pokemons.push(uniqResponse);

with

const index = uniqResponse.id - 1;
this.pokemons[index] = uniqResponse;

Check out my StackBlitz Demo. You can see the pokemon Ids displayed in order.

Related