Arska22
Arska22

Reputation: 11

How can I get the right photos for the searched Pokémon in svelte

Here is the app.svelte code,

I have a search bar there where you can search the Pokémon by the name of it, but it does not show the right photo of the searched Pokémon :

<script>
  import { onMount } from 'svelte';
  import PokemonCard from './PokemonCard.svelte';
  import { Circle3 } from 'svelte-loading-spinners';
  let pokemons = [];

  onMount(async () => {
    await new Promise((resolve) => setTimeout(resolve, 3000));
    const response = await fetch('https://pokeapi.co/api/v2/pokemon?limit=151');
    if (!response.ok) {
      throw new Error('Failed to fetch pokemons');
    }
    const data = await response.json();
    pokemons = data.results;
  });
  let searchString = '';
  $: selectedMonsters = pokemons.filter((pokemon) => {
    return pokemon.name
      .toLowerCase()
      .includes(searchString.toLocaleLowerCase());
  });
</script>

<main>
  <header>
    <input
      class="search"
      type="text"
      bind:value={searchString}
      placeholder="Pokemon Name"
    />
  </header>
  <div class="container">
    <ul class="grid">
      {#each selectedMonsters as { name }, index (index)}
        <PokemonCard {name} {index} />
      {:else}
        <div class="center">
          <h1>First generation Pokémons are loading...</h1>
          <Circle3 />
        </div>
      {/each}
    </ul>
  </div>
</main>

And here is the PokemonCard.svelte :

<script>
  export let name;
  export let index;
  const imgUrl = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${
    index + 1
  }.png`;
</script>

<div class="Card">
  <h2>{name}</h2>

  <div>
    <img src={imgUrl} alt="pokeImg" style="width: 150px; height: 150px;" />
  </div>
</div>

I have tried many things but they are not working I think I know why it is not working but I don't how to fix it.

Upvotes: 1

Views: 61

Answers (1)

Nils K&#228;hler
Nils K&#228;hler

Reputation: 3001

You have 2 things that are stopping you from changing the images.

  1. You send the index of the list, so even if you sort the list it will always use the index to get the image, resulting in always getting bulbasaur as the first image. You need to send the id from the url that you are getting when you are getting the data. Using this line to get the pokemon id from the url-> pokemon.url.split('/').at(-2) splitting all / and then getting the second last item, since the last item is empty since the url ends with a /.
  2. Your image tag does not update when changing the url, so you can move the img src to the template instead of setting it in the script part, this will force it to renew. When you are setting it in a string template the data does not update.

This will give you a list that updates.

// App.svelte

<script>
  import { onMount } from 'svelte';
  import PokemonCard from './PokemonCard.svelte';
  import { Circle3 } from 'svelte-loading-spinners';
  let pokemons = [];
    let searchString = '';

  onMount(async () => {
    await new Promise((resolve) => setTimeout(resolve, 3000));
    const response = await fetch('https://pokeapi.co/api/v2/pokemon?limit=151');
    if (!response.ok) {
      throw new Error('Failed to fetch pokemons');
    }
    let data = await response.json();
    pokemons = data.results.map(pokemon => {
            return {name: pokemon.name, url: pokemon.url.split('/').at(-2)}
        });
  });
  
  $: selectedMonsters = pokemons.filter((pokemon) => {
    return pokemon.name
      .toLowerCase()
      .includes(searchString.toLocaleLowerCase());
  });
</script>

<main>
  <header>
    <input
      class="search"
      type="text"
      bind:value={searchString}
      placeholder="Pokemon Name"
    />
  </header>
  <div class="container">
    <ul class="grid">
      {#each selectedMonsters as {name, url}}
            {name}:{url}
        <PokemonCard {name} {url} />
      {:else}
        <div class="center">
          <h1>First generation Pokémons are loading...</h1>
          <Circle3 />
        </div>
      {/each}
    </ul>
  </div>
</main>

// PokemonCard.svelte

<script>
  export let name;
  export let url;
</script>

<div class="Card">
  <h2>{name}:{url}</h2>

  <div>
    <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{url}.png" alt="pokeImg" style="width: 150px; height: 150px;" />
  </div>
</div>

Upvotes: 0

Related Questions