How can I make a function that filters the api data based on input value?

How can I make a function with the array filter method to filter a list of countries based on what the user types inside the input field?

let countryName = document.getElementById("searchInput");
let url = "https://restcountries.eu/rest/v2/all/";

function getData() {
  return fetch(url)
    .then((res) => res.json())
    .catch((err) => console.log("Handle this error", err));
}

console.log(getData());

function cardTemplate(cardData) {
  const card = document.createElement("div");
  card.innerHTML = `<div class="user">
        <img src="${cardData.flag}" alt="" class="flag">
        <h1 class="countryName">${cardData.name}</h1>
      </div> `;

  return card;
}

function render(container, templates) {
  const d = document.createDocumentFragment();
  templates.forEach((template) => d.appendChild(template));
  container.appendChild(d);
}

function init() {
  const container = document.querySelector(".searchResult");
  getData()
    .then((json) => json.map(cardTemplate))
    .then((templates) => render(container, templates));
}

init();

Hi @KarimZ, you’d store the promise returned from getData() so that you don’t have to fetch the entire data anew each time, and then add an input event listener to the search field to populate the container. The filtering would have to take place before mapping the data to the document fragments then:

function init () {
  const countryName = document.getElementById('searchInput')
  const container = document.querySelector('.searchResult')
  const dataPromise = getData()

  countryName.addEventListener('input', event => {
    container.innerHTML = ''

    dataPromise
      .then(json => json.filter(country => {
        return country.name === event.target.value
      }))
      .then(json => json.map(cardTemplate))
      .then(templates => render(container, templates))
  })
}

This would check for exact equality though, which is probably a bit strict; you might first convert both strings to lower case and use includes() instead, or even allow regular expressions so that for instance afg matches Afghanistan:

// ...
countryName.addEventListener('input', event => {
  container.innerHTML = ''

  dataPromise
    .then(json => json.filter(country => {
      return RegExp(event.target.value, 'i').test(country.name)
    }))
    .then(json => json.map(cardTemplate))
    .then(templates => render(container, templates))
})
2 Likes

Thank you!
Exactly what I was looking for.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.