简体   繁体   中英

Can't make a search based on input value using fetched data . Getting a filter error

Attempting to make an inquiry which depends on input esteem. I am utilizing countries rest programming interface. The wished yield is the parsed information from API which is templated by handlebars markup. It would be ideal if you clarify in what capacity can fix my code. Much obliged to you.

import markupAdd from "../templates/markup.hbs";
const divInfo = document.querySelector("#main-container");
const search_input = document.querySelector(".input-field");
let search_term = "";
let countries;


const fetchCountries = () => {
  countries = fetch(
    "https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
  ).then((res) => res.json());
};

const showCountries = () => {
  divInfo.innerHTML = "";
  fetchCountries();
  countries
    .filter((country) =>
      country.name.toLowerCase().includes(search_term.toLowerCase())
    )
    .map((item) => markupAdd(item))
    .join("");
  divInfo.insertAdjacentHTML("beforeend", infoBlock);
};

search_input.addEventListener("input", (e) => {
  search_term = e.target.value;
  showCountries();
});

handlebars

<div id="country-container">
    <p class="country">{{name}}</p>
    <img src="{{flag}}" alt="{{name}}" width="600" height="400">
    <div id="info-container">
        <p class="capital">Capital: {{capital}}</p>
        <p class="population">Population: {{population}} </p>
        <ul class="langs">
            {{#each languages}}
            <li class="language">Languages: {{name}}</li>
            {{/each}}
        </ul>
    </div>
</div>

At the present time, after inputed any letter I am getting this kind of error

apiInfo.js?b765:22 Uncaught TypeError: countries.filter is not a function
    at showCountries (apiInfo.js?b765:22)
    at HTMLInputElement.eval (apiInfo.js?b765:28)

The fetchCounries function is not returning anything, one approch to solve the issue will be following.

  • Convert the Function to the async function
  • and then return the data your will get.
const fetchCountries = async () => {
  let countries = await fetch(
    "https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
  );
  let country =  await countries.json();
  return country;
};

const showCountries = () => {
  divInfo.innerHTML = "";
  fetchCountries().then(countries =>{
    countries
    .filter((country) =>
      country.name.toLowerCase().includes(search_term.toLowerCase())
    )
    .map((item) => markupAdd(item))
    .join("");
    divInfo.insertAdjacentHTML("beforeend", infoBlock);
  }).catch(err => {
      console.log(err)
  })
};

Async Function also returns a promise so later you can handle this using then catch block

to do it without the async await and do it more clear, you can do something like this

const fetchCountries = () => {
  fetch(
    "https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
  )
    .then((res) => res.json())
    .then((data) => {
      showCountries(data);
    })
    .catch((err) => {
      console.log(err);
    });
};

const showCountries = (countries) => {
  divInfo.innerHTML = "";
  countries
    .filter((country) =>
      country.name.toLowerCase().includes(search_term.toLowerCase())
    )
    .map((item) => markupAdd(item))
    .join("");
  divInfo.insertAdjacentHTML("beforeend", infoBlock);
};

Change your function like this:

async function fetchCountries() {
  response = await fetch ("https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages");
return await response.json();
};

And where you are calling the function, just use.then to get the data.

fetchCountries().then().catch();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM