Populating Drop down list from selection to another drop down value not show

Viewed 805

Im having a trouble on how can I populate data to my third dropdown.
I have three dropdown, firstly when I click my first dropdown the second dropdown will populate list based on the value of my first dropdown and below my code it works fine.
The problem is, I want to populate list to my third dropdown when I click second dropdown but it didn't show anything.

var mealsByCategory = 
    { A: [ 'San Francisco', 'Manila', 'Kirishima' ] 
    , B: [ 'b', 'bb', 'bbb', 'bbbb' ] 
    , C: [ 'c', 'ccc', 'cccc', 'ccccc', 'cccccc' ] 
    } 
var Mprovinces = 
    { A: [ 'San Francisco', 'Manila', 'Kirishima' ] 
    , B: [ 'b', 'bb', 'bbb', 'bbbb' ] 
    , C: [ 'c', 'ccc', 'cccc', 'ccccc', 'cccccc' ] 
    } 
    
function changemeal(value) {
  $('#category').prop('disabled', false);
  if (value.length == 0) document.getElementById("category").innerHTML = "<option></option>";
  else {
    var catOptions = "";
    for (categoryId in mealsByCategory[value]) {
      catOptions += "<option>" + mealsByCategory[value][categoryId] + "</option>";
    }
    document.getElementById("category").innerHTML = catOptions;
  }
}

function changecat(value) {
  $('#provinces').prop('disabled', false);
  if (value.length == 0) document.getElementById("provinces").innerHTML = "<option></option>";
  else {
    var catOptions1 = "";
    for (categoryId in Mprovinces[value]) {
      catOptions1 += "<option>" + Mprovinces[value][categoryId] + "</option>";
    }
    document.getElementById("provinces").innerHTML = catOptions1;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select onChange="changemeal(this.value);">
  <option value="" disabled selected>Select Province</option>
  <option value="A">Usa</option>
  <option value="B">Japan</option>
  <option value="C">China</option>
</select>

<select name="category" id="category" onChange="changecat(this.value);" disabled>
  <option disabled selected>Select</option>
  <option value="A">Usa</option>
  <option value="B">Japan</option>
  <option value="C">China</option>
</select>

<select name="provinces" id="provinces" disabled>
  <option value="" disabled selected>Select</option>
</select>

3 Answers

my way...

const f_Geo = document.getElementById('geographia-form')
 , selOrder = [ 'region', 'land', 'city' ] // hierarchical order of selects
 , treeData =
    [ { id:  1, name: 'USA',           parentID:  0 }
    , { id:  2, name: 'Japan',         parentID:  0 }
    , { id:  3, name: 'Europe',        parentID:  0 }
    , { id:  4, name: 'California',    parentID:  1 }
    , { id:  5, name: 'Oklahoma',      parentID:  1 }
    , { id:  6, name: 'Arizona',       parentID:  1 }
    , { id:  7, name: 'Kantô',         parentID:  2 }
    , { id:  8, name: 'Kansai',        parentID:  2 }
    , { id:  9, name: 'Chügoku',       parentID:  2 }
    , { id: 10, name: 'France',        parentID:  3 }
    , { id: 11, name: 'Deutschland',   parentID:  3 }
    , { id: 12, name: 'Espana',        parentID:  3 }
    , { id: 13, name: 'Sacramento',    parentID:  4 }
    , { id: 14, name: 'Los Angeles',   parentID:  4 }
    , { id: 15, name: 'San Diego',     parentID:  4 }
    , { id: 16, name: 'Tulsa',         parentID:  5 }
    , { id: 17, name: 'Oklahoma City', parentID:  5 }
    , { id: 18, name: 'Lawton',        parentID:  5 }
    , { id: 19, name: 'Phoenix',       parentID:  6 }
    , { id: 20, name: 'Flagstaff',     parentID:  6 }
    , { id: 21, name: 'Tucson',        parentID:  6 }
    , { id: 21, name: 'Tokyo',         parentID:  7 }
    , { id: 22, name: 'Chiba',         parentID:  7 }
    , { id: 23, name: 'Tochigi',       parentID:  7 }
    , { id: 24, name: 'Kyoto',         parentID:  8 }
    , { id: 25, name: 'Osaka',         parentID:  8 }
    , { id: 26, name: 'Nara',          parentID:  8 }
    , { id: 27, name: 'Tottori',       parentID:  9 }
    , { id: 28, name: 'Hirochima',     parentID:  9 }
    , { id: 29, name: 'Okayama',       parentID:  9 }
    , { id: 30, name: 'Quimper',       parentID: 10 }
    , { id: 31, name: 'Toulouse',      parentID: 10 }
    , { id: 32, name: 'Nancy',         parentID: 10 }
    , { id: 33, name: 'Dusseldorf',    parentID: 11 }
    , { id: 34, name: 'Leipzig',       parentID: 11 }
    , { id: 35, name: 'Munchen',       parentID: 11 }
    , { id: 36, name: 'Barcelona',     parentID: 12 }
    , { id: 37, name: 'Sevilla',       parentID: 12 }
    , { id: 38, name: 'Guernica',      parentID: 12 }
    ]
  ;
f_Geo.onsubmit=e=>e.preventDefault()  // disable submit
  ;
f_Geo.onchange=e=>
  {
  //if (!e.target.matches('select')) return  
  setSubSelects(e.target.name)
  }
function setSelect(name,id)
  {
  f_Geo[name].innerHTML = '' // clear select
  treeData.filter(el=>el.parentID===id)
          .forEach(el=>{ f_Geo[name].add( new Option(el.name, el.id)) })
  }
function setSubSelects(selectName)
  {
  let idx = selOrder.findIndex(x=>x===selectName) +1
  if (idx < selOrder.length)
    {
    let sName = selOrder[idx]
    setSelect ( sName,  +f_Geo[selectName].value )
    setSubSelects(sName)
    }
  }

setSelect('region',0)
setSubSelects('region')
<form action="" id="geographia-form">
  <select name="region"></select>
  <select name="land"></select>
  <select name="city"></select>
</form>

Using a completely customisable way:

let data = [{"id":1,"name":"USA","parentid":0},
{"id":2,"name":"Japan","parentid":0},
{"id":3,"name":"Europe","parentid":0},
{"id":4,"name":"California","parentid":1},
{"id":5,"name":"Oklahoma","parentid":1},
{"id":6,"name":"Arizona","parentid":1},
{"id":7,"name":"Kantô","parentid":2},
{"id":8,"name":"Kansai","parentid":2},
{"id":9,"name":"Chügoku","parentid":2},
{"id":10,"name":"France","parentid":3},
{"id":11,"name":"Deutschland","parentid":3},
{"id":12,"name":"Espana","parentid":3},
{"id":13,"name":"Sacramento","parentid":4},
{"id":14,"name":"Los Angeles","parentid":4},
{"id":15,"name":"San Diego","parentid":4},
{"id":16,"name":"Tulsa","parentid":5},
{"id":17,"name":"Oklahoma City","parentid":5},
{"id":18,"name":"Lawton","parentid":5},
{"id":19,"name":"Phoenix","parentid":6},
{"id":20,"name":"Flagstaff","parentid":6},
{"id":21,"name":"Tucson","parentid":6},
{"id":21,"name":"Tokyo","parentid":7},
{"id":22,"name":"Chiba","parentid":7},
{"id":23,"name":"Tochigi","parentid":7},
{"id":24,"name":"Kyoto","parentid":8},
{"id":25,"name":"Osaka","parentid":8},
{"id":26,"name":"Nara","parentid":8},
{"id":27,"name":"Tottori","parentid":9},
{"id":28,"name":"Hirochima","parentid":9},
{"id":29,"name":"Okayama","parentid":9},
{"id":30,"name":"Quimper","parentid":10},
{"id":31,"name":"Toulouse","parentid":10},
{"id":32,"name":"Nancy","parentid":10},
{"id":33,"name":"Dusseldorf","parentid":11},
{"id":34,"name":"Leipzig","parentid":11},
{"id":35,"name":"Munchen","parentid":11},
{"id":36,"name":"Barcelona","parentid":12},
{"id":37,"name":"Sevilla","parentid":12},
{"id":38,"name":"Guernica","parentid":12}]

function populateList(list, pid) {
  let l = document.getElementById(list);
  l.innerHTML = "";
  let topItem = document.createElement("option");
  topItem.value = 0;
  topItem.text = "--Select--";
  l.appendChild(topItem); 
  let items = data.filter(item => item.parentid == pid);
  items.forEach(function(item){
    let newItem = document.createElement("option");
    newItem.value = item.id;
    newItem.text = item.name;
    l.appendChild(newItem);
  })
}

function updateList(selList, thisList) {
  if (thisList.value != 0) {
    populateList(selList, Number(thisList.value));
  } else {
    let s = document.getElementById(selList);
    s.value = 0;
    triggerEvent(s, "onchange");
    let sCopy = s.cloneNode(false);
    let p = s.parentNode;
    p.replaceChild(sCopy, s);
  }
}
function triggerEvent(e, trigger)
{
    if ((e[trigger] || false) && typeof e[trigger] == 'function')
    {
        e[trigger](e);
    }
}
 

function loadList1() {
  populateList("list1", 0);
}

window.onload = loadList1;
select {width:150px;}
Region: <select id="list1" onchange="updateList('list2', this);"></select>
Sub-region:<select id="list2" onchange="updateList('list3', this);"></select>>
Location:<select id="list3"></select>

As long as the data structure is the same - ie {"id":n, "name":"xxx", "parentid":n} then the only change is the text next to each of the lists - otherwise, the function just needs to be updated to use the key names provided. And, as all we are doing is populating lists based on the same array, they can all use the same base function - populateList. The initial load and the selection from a list start off differently, but end up doing the same thing - filling a list based on the filtered array.

function getText() {
  let thisList = document.getElementById("list1");
  console.log(thisList.value);
  console.log(thisList[thisList.selectedIndex].text);

}
<button onclick="getText();">Click</button>

<select id="list1">
  <option value="1">Text 1</option>
  <option value="2">Text 2</option>
  <option value="3">Text 3</option>
</select>

OK - this is a very rough-and-ready example that I've just put together to give you an idea on the data structure and the javascript:

let data = [{"id":1, "displaytext":"England", "parentid": 0},
{"id":2, "displaytext":"Scotland", "parentid": 0},
{"id":3, "displaytext":"Wales", "parentid": 0},
{"id":4, "displaytext":"Northern Ireland", "parentid": 0},
{"id":5, "displaytext":"London", "parentid": 1},
{"id":6, "displaytext":"Birmingham", "parentid": 1},
{"id":7, "displaytext":"Manchester", "parentid": 1},
{"id":8, "displaytext":"Edinburgh", "parentid": 2},
{"id":9, "displaytext":"Glasgow", "parentid": 2},
{"id":10, "displaytext":"Dundee", "parentid": 2},
{"id":11, "displaytext":"Cardiff", "parentid": 3},
{"id":12, "displaytext":"Swansea", "parentid": 3},
{"id":13, "displaytext":"Belfast", "parentid": 4},
{"id":14, "displaytext":"Lisburn", "parentid": 4}]

function loadParents() {
  let oList = document.getElementById("parent");
  let parents = data.filter(item => item.parentid == 0);
  let topItem = document.createElement("option");
  topItem.value = 0;
  topItem.text = "--Select--";
  oList.appendChild(topItem);
  parents.forEach(function(parent) {
    let newItem = document.createElement("option");
    newItem.value = parent.id;
    newItem.text = parent.displaytext;
    oList.appendChild(newItem);
  
  })
}

function getChildren() {
  let oList = document.getElementById("parent");
  let cList = document.getElementById("child");
  cList.innerHTML = "";
  let oFilter = oList.value;
  if (oList.value != 0) {
    let children = data.filter(item => item.parentid == oFilter);
    let topItem = document.createElement("option");
      topItem.value = 0;
      topItem.text = "--Select--";
      cList.appendChild(topItem);
    children.forEach(function(child) {
      let newItem = document.createElement("option");
      newItem.value = child.id;
      newItem.text = child.displaytext;
      cList.appendChild(newItem);
    })
  }
}


window.onload = loadParents;
<select id="parent" onchange="getChildren()";></select><select id="child"></select>

This is just a simple list of UK countries and some of their cities. Select a country from the first list and the second list is replaced by the "children" of that "parent".

Related