How can I write a For loop from dropdown box to populate second dropdown box from JSON file?

Viewed 194

I have a Jinja for loop populating one dropdown box for countries. This allows a user to select a country. But I have second Jinja for loop populating a second dropdown box for states. At the moment, the second dropdown box just iterates every state in the list (which is 1000s).

So I am building a JavaScript to iterate through the JSON file and collect the data of the user chosen country to populate the state's list with only states that are associated with that particular country.

Unfortunately, this is where I get stuck. I am not too familiar with the common concept of a for loop in JS.

So far I can pick this:

document.getElementById("country").addEventListener("change", function() {
    const country_change = document.getElementById("country").value;
    console.log(country_change);
    console.log(countries);
}); 

Where country_change is the user-chosen country and countries is the entire JSON file.

console.log

Clicking on the countries log first entry I get:

countries

This is what I want to iterate through to:

states

I can call all the countries from the JSON file into JS, now when a user selects a country I have that variable, so now I want to look through states for that country and its associated states.

I tried a simple for loop from w3 schools just to see what comes out - but there wasn't anything really useful that I could gather. I think I just need a bit more of a shove in the right direction.

Edit: Just experimenting with:

document.getElementById("country").addEventListener("change", function() {
    const country_change = document.getElementById("country").value;
    console.log(country_change);
    console.log(countries);
    const Ind = countries.findIndex(e => {
       return e['name'] === country_change
      })
      if(Ind != -1){
      countries[Ind]['states'].forEach(e=>console.log(e))
      }
});

But still not producing the desired results.

2 Answers

You could do something like this:

Every time the country dropdown value changes, update all state options.

function updateSelect({ node, values }) {
    while (node.hasChildNodes()) node.removeChild(node.lastChild)
    for (const value of values) {
        const option = document.createElement("option")
        option.value = option.textContent = value
        node.appendChild(option)
    }
}

// Sample data
const countries = [
    {
        name: "Germany",
        states: ["Bavaria", "Berlin", "Saxony"]
    },
    {
        name: "Austria",
        states: ["Tyrol", "Vienna"]
    }
]

const coutriesSelect = document.querySelector("#country")
const statesSelect = document.querySelector("#state")

updateSelect({
    node: coutriesSelect,
    values: countries.map(country => country.name),
})
// Update it on initialization
updateStatesSelect()
coutriesSelect.addEventListener("change", updateStatesSelect)

function updateStatesSelect() {
    const countryName = coutriesSelect.value
    const country = countries.find(country => country.name === countryName)
    const states = country.states
    updateSelect({
        node: statesSelect,
        values: states
    })
}
<select name="country" id="country"></select>
<select name="state" id="state"></select>

It appears this will iterate through that list and produce the states:

const Ind = countries.findIndex(e => {
       return e['name'] === country_change
      })
      if(Ind != -1){
      countries[Ind]['states'].forEach(e=>console.log(e))
      }

Based on the data I have given.

Related