首页 > 解决方案 > Search filter for PokeAPI

问题描述

Hi I'm making a search filter from the PokeAPI, but I'm getting a TypeError: Cannot read property 'filter' of undefined at HTMLInputElement. I want that when searching for a pokemon that it shows up. I probably do something wrong it could be a great help if some could help me with it. Thank you for your help.

const PokemonContainer = document.getElementById('pokemon__containerID');
const SearchContainer = document.getElementById('search__containerID');
const SearchElement = document.createElement('input');
SearchElement.setAttribute('type', 'text');
SearchElement.setAttribute('name', 'searchBar');
SearchElement.setAttribute('placeholder', 'Search...');
SearchContainer.appendChild(SearchElement);
const PokemonNumber = 151;

const createPokemonCard = (pokemon) => {
    const PokemonElement = document.createElement('div');
    const PokemonName = pokemon.name[0].toUpperCase() + pokemon.name.slice(1);
    const PokemonID = pokemon.id;
    const PokemonType = pokemon.types[0].type.name;
    const PokemonTypeColors = {
        fire: '#EE8130',
        grass: '#7AC74C',
        eletric: '#F7D02C',
        water: '#6390F0',
        ground: '#E2BF65',
        rock: '#B6A136',
        fairy: '#D685AD',
        poison: '#A33EA1',
        bug: '#A6B91A',
        dragon: '#6F35FC',
        psychic: '#F95587',
        flying: '#A98FF3',
        fighting: '#C22E28',
        normal: '#A8A77A',
        ice: '#96D9D6',
        ghost: '#735797',
        dark: '#705746',
        steel: '#B7B7CE',
    };
    const AddColors = PokemonTypeColors[PokemonType];
    PokemonElement.style.backgroundColor = AddColors;
    const PokemonInnerHTML = `
    <div class="pokemon__imageContainer">
    <img src="https://pokeres.bastionbot.org/images/pokemon/${PokemonID}.png" />
    </div>
    <div class="pokemon__infomationContainer">
    <span class="pokemon__id">#${PokemonID.toString().padStart(3, '0')}</span>
    <h3 class="pokemon__name">${PokemonName}</h3>
    <small class="pokemon__type">Type: <span>${PokemonType}</span></small>
    </div>`;
    PokemonElement.setAttribute('class', 'pokemon__card');
    PokemonElement.innerHTML = PokemonInnerHTML;
    PokemonContainer.appendChild(PokemonElement);
};

const getPokemons = async (id) => {
    const api_url = `https://pokeapi.co/api/v2/pokemon/${id}`;
    const response = await fetch(api_url);
    const data = await response.json();
    createPokemonCard(data);
    createSearchFilter(data);
};

const receivePokemons = async () => {
    for (let item = 1; item <= PokemonNumber; item++) {
        await getPokemons(item);
    }
};

receivePokemons();

const createSearchFilter = (pokemonData) => {
    console.log(pokemonData);
    SearchElement.addEventListener('keyup', (event) => {
        const SearchValue = event.target.value;
        const FilteredPokemons = pokemonData.filter((pokemon) => {
            return (
                pokemon.name.includes(SearchValue) || pokemon.id.includes(SearchValue)
            );
        });
        createPokemonCard(FilteredPokemons);
        console.log(FilteredPokemons);
    });
};

createSearchFilter();
@import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background: #efefbb;
    background: -webkit-linear-gradient(to right, #d4d3dd, #efefbb);
    background: linear-gradient(to right, #d4d3dd, #efefbb);

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-family: 'Lato';
}

h1 {
    letter-spacing: 3px;
}

.pokemon__container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: space-between;
    max-width: 100vw;
}

.pokemon__card {
    background: #eeeeee;
    border-radius: 20px;
    padding: 20px 40px;
    margin: 10px;
    box-shadow: 0 3px 15px rgba(100, 100, 100, 0.6);
}

.pokemon__imageContainer {
    margin-top: 20px;
    width: 120px;
    height: 120px;
}

.pokemon__imageContainer img {
    width: 100%;
}

.pokemon__infomationContainer {
    margin-top: 20px;
    text-align: center;
}

.pokemon__id {
    background: #ffffff80;
    border-radius: 10px;
    font-size: 1rem;
    padding: 5px 10px;
}

.pokemon__name {
    margin: 15px 0 7px 0;
    letter-spacing: 1px;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="function.js" defer></script>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <h1>PokeDex</h1>
        <div class="search__container" id="search__containerID"></div>
        <div class="pokemon__container" id="pokemon__containerID"></div>
    </body>
</html>

标签: javascript

解决方案


  • 问题是你在createSearchFilter里面一次又一次地打电话,getPokemons这是问题的根源。

  • 我的建议是在您获得所有日期调用createSearchFilter一次并且无需传递任何数据之后,我们将隐藏/显示 DOM 元素。

  • 我建议的另一件事是添加一个id并将pokemon__card其设置为等于口袋妖怪的名称,这将使搜索变得相当简单。 PokemonElement.setAttribute("id", PokemonName);

  • 接下来,内部createSearchFilter函数从 DOM 中获取所有口袋妖怪卡片并监听keyup事件。在事件侦听器中检查卡片是否id包含搜索词。

    • 如果是,请将卡的显示设置为block
    • 如果没有,请将其设置为none.

const PokemonContainer = document.getElementById("pokemon__containerID");
const SearchContainer = document.getElementById("search__containerID");

const SearchElement = document.createElement("input");
SearchElement.setAttribute("type", "text");
SearchElement.setAttribute("name", "searchBar");
SearchElement.setAttribute("placeholder", "Search...");
SearchContainer.appendChild(SearchElement);

const PokemonNumber = 10;

const createPokemonCard = (pokemon) => {
  const PokemonElement = document.createElement("div");
  const PokemonName = pokemon.name[0].toUpperCase() + pokemon.name.slice(1);
  PokemonElement.setAttribute("id", PokemonName);
  const PokemonID = pokemon.id;
  const PokemonType = pokemon.types[0].type.name;
  const PokemonTypeColors = {
    fire: "#EE8130",
    grass: "#7AC74C",
    eletric: "#F7D02C",
    water: "#6390F0",
    ground: "#E2BF65",
    rock: "#B6A136",
    fairy: "#D685AD",
    poison: "#A33EA1",
    bug: "#A6B91A",
    dragon: "#6F35FC",
    psychic: "#F95587",
    flying: "#A98FF3",
    fighting: "#C22E28",
    normal: "#A8A77A",
    ice: "#96D9D6",
    ghost: "#735797",
    dark: "#705746",
    steel: "#B7B7CE",
  };
  const AddColors = PokemonTypeColors[PokemonType];
  PokemonElement.style.backgroundColor = AddColors;
  const PokemonInnerHTML = `
    <div class="pokemon__imageContainer" id="${PokemonName}">
      <img src="https://pokeres.bastionbot.org/images/pokemon/${PokemonID}.png" />
    </div>
    <div class="pokemon__infomationContainer">
      <span class="pokemon__id">#${PokemonID.toString().padStart(3, "0")}</span>
      <h3 class="pokemon__name">${PokemonName}</h3>
      <small class="pokemon__type">Type: <span>${PokemonType}</span></small>
    </div>`;
  PokemonElement.setAttribute("class", "pokemon__card");
  PokemonElement.innerHTML = PokemonInnerHTML;
  PokemonContainer.appendChild(PokemonElement);
};

const getPokemons = async (id) => {
  const api_url = `https://pokeapi.co/api/v2/pokemon/${id}`;
  const response = await fetch(api_url);
  const data = await response.json();
  createPokemonCard(data);
};

const receivePokemons = async () => {
  for (let item = 1; item <= PokemonNumber; item++) {
    await getPokemons(item);
  }
  createSearchFilter();
};

receivePokemons();

const createSearchFilter = (pokemonData) => {
  const cards = document.querySelectorAll(".pokemon__card");
  SearchElement.addEventListener("keyup", (event) => {
    const val = event.target.value.toLowerCase();
    cards.forEach((card) => {
      if (card.id.toLowerCase().includes(val)) {
        card.style.display = "block";
      } else {
        card.style.display = "none";
      }
    });
  });
};
@import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #efefbb;
  background: -webkit-linear-gradient(to right, #d4d3dd, #efefbb);
  background: linear-gradient(to right, #d4d3dd, #efefbb);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-family: 'Lato';
}

h1 {
  letter-spacing: 3px;
}

.pokemon__container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: space-between;
  max-width: 100vw;
}

.pokemon__card {
  background: #eeeeee;
  border-radius: 20px;
  padding: 20px 40px;
  margin: 10px;
  box-shadow: 0 3px 15px rgba(100, 100, 100, 0.6);
}

.pokemon__imageContainer {
  margin-top: 20px;
  width: 120px;
  height: 120px;
}

.pokemon__imageContainer img {
  width: 100%;
}

.pokemon__infomationContainer {
  margin-top: 20px;
  text-align: center;
}

.pokemon__id {
  background: #ffffff80;
  border-radius: 10px;
  font-size: 1rem;
  padding: 5px 10px;
}

.pokemon__name {
  margin: 15px 0 7px 0;
  letter-spacing: 1px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <script src="function.js" defer></script>
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <h1>PokeDex</h1>
  <div class="search__container" id="search__containerID"></div>
  <div class="pokemon__container" id="pokemon__containerID"></div>
</body>

</html>


推荐阅读