javascriptfilterdrop-down-menu

Filter Select (Drop Down) Options Based on Value Selected in another Select


I have code below that is populating a select with values from the result array. - What I want to do is create an additional select that will filter the results based on the value {tag} selected.

For example:

I want the first select to only have the tags as options, based on the tag selected, the second select will only show names filtered by the selected tag.

I am also open to opinions on better ways to do this, for instance, if radio options work better for the filter then I would use those. - Thanks in advance!

UPDATE: Snippet has been changed to include additional select with tag values. Just need to figure out how to make the second select change based on the tag selected in the first select.

let result = [
  {name: "some name", tag: "some tag"},
  {name: "some name1", tag: "some tag1"},
  {name: "some name2", tag: "some tag2"},
  {name: "some name2-2", tag: "some tag2"}
];

let hcList = document.getElementById("hclist");
Object.keys(result).map((key) => hcList.add(new Option(result[key].name, JSON.stringify(result[key]))));

    let uniqueTags = [...new Set(result.map((item) => item.tag))];

    let tagList = document.getElementById("taglist");
    Object.keys(uniqueTags).map((key) =>
      tagList.add(new Option(uniqueTags[key]))
    );
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
</head>
<body>
<select id="taglist"></select>
  <select id="hclist"></select>
</body>
</html>


Solution

  • See this. I have added comments wherever necessary:

    let result = [
      {name: "some name", tag: "some tag"},
      {name: "some name1", tag: "some tag1"},
      {name: "some name2", tag: "some tag2"},
      {name: "some name2-2", tag: "some tag2"}
    ];
    
    //Generic function to fill a dropdown with options 
    let populateDropDown = (params) => {
        params.optionsToPopulate.forEach(item => {
            params.ddlElement.add(new Option(item[`${params.text}`], item[`${params.text}`]))
        })
    }
    
    //Initialize tags dropdown
    (function(){
      document.getElementById("tagsDdl").addEventListener('change', (event) => {
        tagChanged(event);
      });
    
        let params = {
            optionsToPopulate:result,
            ddlElement:document.getElementById("tagsDdl"),
            id:"tag",
            text:"tag"
        }
        populateDropDown(params);
    
        //Uncomment the below code if you want to set names dropdown on page load based on the value of tags dropdown on pageload
        /*  let paramsNames = {
                optionsToPopulate:result.filter(item => item.tag === document.getElementById("tagsDdl").value),
                ddlElement:document.getElementById("namesDdl"),
                id:"name",
                text:"name"
            }
            populateDropDown(paramsNames);*/
    
    })();
    
    //Tags dropdown change event.
    let tagChanged = (event) => {   
        let tagDdlValue = event.target.value;
    
        //filter the results based on the value of tags dropdonw
        let optionsToAdd = result.filter(item => item.tag === tagDdlValue);
        let namesDdl = document.getElementById("namesDdl");
        namesDdl.options.length=0;
        let params = {
            optionsToPopulate:optionsToAdd,
            ddlElement:namesDdl,
            id:"name",
            text:"name"
        }   
        populateDropDown(params);
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
    </head>
    <body>
      Tags DDL: <select id="tagsDdl"></select> 
    
      <br><br><br>
      Names DDL: <select id="namesDdl"></select>
    </body>
    </html>