javascriptdrop-down-menumap-function

Populate select (drop down) with data from API after .map using vanilla JS


I am stuck on a problem. I am using code that looks something like the following to populate a select with data but I am not getting the expected result.

let data = await response.json();
let result = data.checks.map((check) => {
  return {
    name: check.name,
    tag: check.tags,
  };
});
let hcList = document.getElementById("hclist");
Object.keys(result).map((key) => hcList.add(new Option(result[key], key)));
return result;
}
getHcList().then((result) => console.log(result));

The select populates but looks like this enter image description here

Here is what the result data looks like in console:

0: {name: "some name", tag: "some tag"}
1: {name: "some name1", tag: "some tag1"}
2: {name: "some name2", tag: "some tag2"}

I would like for just the name to populate this select. - Must use vanilla JS.


Solution

  • Your issue lies within your map() call, when you invoke new Option().

    According to the Option() syntax on MDN, the first argument in the Option constructor is the text to display, and the second is the data the select option should point to when a given option is chosen. Since your key is really just an array index, what your current code is doing is displaying the object as "text" ([object Object]), and passing the index as data when selected.

    Change

    hcList.add(new Option(result[key], key))
    

    to

    hcList.add(new Option(result[key].name, JSON.stringify(result[key])))
    

    to fix your problem. The JSON.stringify() is required because the value attribute only supports strings (Without it, the string [object Object] will be stored as your value!).

    let result = [
      {name: "some name", tag: "some tag"},
      {name: "some name1", tag: "some tag1"},
      {name: "some name2", tag: "some tag2"}
    ];
    
    let hcList = document.getElementById("hclist");
    Object.keys(result).map((key) => hcList.add(new Option(result[key].name, JSON.stringify(result[key]))));
    
    //Event listener to display value attribute for clarity
    hcList.addEventListener("input", () => document.getElementById("optionData").innerHTML = hcList.value);
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
    </head>
    <body>
      <select id="hclist"></select>
      <p>Selected:</p>
      <p id="optionData"></p>
    </body>
    </html>

    A side note: If you know that the data coming in is in array format, which it seems yours is since the console log you provided lists indexes in front of your objects, you can simplify your Object.keys(result).map() call to result.map(), like so:

    result.map((key) => hcList.add(new Option(key.name, JSON.stringify(key))));
    // 'key' is now each object element, rather than an index