Pokedex Project 3 - getting a dropdown list
Published: 2023-09-17 11:01:38

Welcome back to the Pokedex project series! In this post we are going to be exploring getting a dropdown list enabled on our SPA.

The goal is for when users are typing out a Pokemon name into the input field, the entire Pokedex will appear based on the letters they have input thus far. I also was considering having their dex entry and maybe a small sprite appear as well.

##Getting started
The first decision I had to make when thinking about the dropdown list was how it should appear on the page and the correct elements I should be using.

As I previously mentioned I had theorised using the <datalist> element to make the list as it would be an easy solution for people to click on and the value would autopopulate into the input field. However it looked terrible and I wasn't able to change the styling due to how the element works within browsers. 

To get around this I decided upon using an unordered list when I would then fetch the Pokemon from the API and have them as list items.

##Starting anew 
As to not completely destroy what I had previously created I decided to test this dropdown field on a new set of files starting from scratch.

I had a brief understanding of how I could get the elements to populate however I came to a crossroads that lead me down a YouTube tutorial rabbit hole to implement this feature.

##First steps
To get started as I mentioned before I started a with a new set of HTML, CSS and JS files as to not ruin what I had already done. The video tutorial I was watching fetched a list of countries and had the filter feature that I was after with the Pokemon.

All I had to do was swap out their API for my own right?

Unfortunately things are never that simple and the solution proved to be a bit more involved. 

So going back to our basics we need to break the problem down into smaller little problems and tackle it one step at a time.

1. Fetch the entire Pokedex list
2. Load the name of each Pokemon
3. Filter the list by the text that a user has input

##Solving the problem
Breaking the problem down into smaller pieces makes things that seem daunting a lot more manageable, especially when you are just a novice in this area.

We had already tackled fetching the API data once, so yay step one done.

Eventually I came to a conclusion that suited what I was after.

const apiUrl = "https://pokeapi.co/api/v2/pokemon/";

let pokemon = [];
const pokemonListElement = document.querySelector('#pokemon-list');
const pokemonInputElement = document.querySelector('#pokemon-input');

function fetchPokemon() {
    fetch(apiUrl + `?limit=1020&offset=0`)
        .then((response) => response.json())
        .then((data) => {
            pokemon = data.results.map((x) => x.name);
            pokemon.sort();
    });
}

function loadData(data, element) {
    if (data) {
        element.innerHTML = "";
        let innerElement = "";
        data.forEach((item) => {
            innerElement += `
            <li>${item}</li>`;
        });

        element.innerHTML = innerElement;
    }
}

function filterData(data, searchText) {
    return data.filter((x) => x.toLowerCase().includes(searchText.toLowerCase()));
}

fetchPokemon();

pokemonInputElement.addEventListener("input", function () {
    const filteredData = filterData(pokemon, pokemonInputElement.value);
    loadData(filteredData, pokemonListElement);
});

###Breakdown of what is happening

1. Declare our API url for ease of use
2. Create an empty array to assign values too
3. Declare our list and element inputs
4. Fetch the entire 1010 Pokedex list
5. Load the data from the API where each Pokemon becomes an LI item
6. Filter the data from the user's input (have included extra measures to not make it case sensitive)
7. Create an event listener that triggers the list to appear once a user has input something

##Styling 
Cool now that this input is working we can adjust the styling for it and since it is an unordered list, we can use CSS for this. At the time this is the CSS I had for this test batch:

.autocomplete-input {
    padding: 25px 15px;
    width: calc(100% - 30px);
    border-radius: 1px;
    border: none;
    outline: none;
    font-weight: bold;
    background-color: #fff;
}

.autocomplete-list {
    position: absolute;
    top: 70px;
    left: 0;
    list-style-type: none;
    margin: 0;
    padding: 0;
    background-color: #fff;
    width: 100%;
    max-height: 200px;
    overflow-y: auto;
}

.autocomplete-list li {
    padding: 15px;
    width: calc(100% - 30px);
    font-weight: bold;
    cursor: pointer;
}

The plan was for it to sit just below the input field and not be too wide as to account for the input field and page length.

##Closing items
Thanks for tuning into part 3! In the next edition I will go over how I implemented this into my current environment and how we went about the styling for the Pokedex itself!