Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

145
Views
Subcategories aren't populating using fetch

I'm trying to create <optgroup>s that have subcategories pulled from an API. Currently, only the <optgroup>s are populating, but not the subcategories.

let select = document.querySelector("#category");
const categoriesURL = "INSERT_URL"
  
let str = "";

fetch(categoriesURL)
  .then(response => response.json())
  .then(data => {
    data.forEach(category => {
      let categoryTitle = category.title;
      str += `<optgroup label=${categoryTitle}></optgroup>`
      category.subcategories.forEach(sub => {
        let subcategories_id = sub.subcategories_id;
        let subcategoriesURL = `INSERT_URL/${subcategories_id}`;
        fetch(subcategoriesURL)
          .then(response => response.json())
          .then(subData => {
          str += `<option value=${sub.subcategories_id}>` + subData.title + "</option>";
        })
      })
  })
  select.innerHTML = "<option disabled selected>Select a category</option>" + str;
});
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

When defining your optgroup in the string, you immediately open and close the optgroup, effectively putting every option after the optgroup.

str += `<optgroup label=${categoryTitle}></optgroup>`

Leave the optgroup open in the aforementioned string.

However, the hard part is closing the string after all the fetch requests on the subcategories are complete. We can accomplish this with Promise.all and Array#map.

Loop over all the subcategories with map and return Promise that fetch returns in the loop. When all the fetch requests are done the code will continue to the then block that follows the Promise.all function. In that block you will have the ids and titles of all your subcategories collected in an array. Loop over array to append to your string.

After the loop, close the optgroup element.

fetch(categoriesURL)
  .then(response => response.json())
  .then(data => {
    data.forEach(category => {
      let categoryTitle = category.title;
      str += `<optgroup label=${categoryTitle}>`;

      Promise.all(category.subcategories.map(sub => {
        let subcategories_id = sub.subcategories_id;
        let subcategoriesURL = `INSERT_URL/${subcategories_id}`;

        return fetch(subcategoriesURL)
          .then(response => response.json())
          .then(({ title }) => ({
            title,
            id: subcategories_id
          }))
      })).then(subData => {
        subData.forEach(({ id, title }) => {
          str += `<option value=${id}>${title}</option>`;
        })
        
        str += '</optgroup>';
      });
    })

    select.innerHTML = "<option disabled selected>Select a category</option>" + str;
  });

Though, overall this a very expensive script as it will create a lot of requests. If you have any say over the backend, then I'd advice that you send the all the data back in a single request and create your list based on that result.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!