Reputation: 11
I am pretty new to JavaScript. I am trying to create dropdowns that are dynamic in the sense that when you select a value in the first dropdown the second dropdown automatically updates for all possible values for the value selected and vice versa.
I am able to do it one way but not the other way around. Please find attached the screenshot of my code here. I would be grateful for any answers. Thanks.
function populate(s1,s2){
var s1 = document.getElementById(s1);
var s2 = document.getElementById(s2);
if (s1.value!=""){
if (s1.value!=""){
s2.innerHTML=""
} else {
s1.innerHTML=""
}
if(s1.value == "Chevy"){
var optionArray = ["|","Camaro|Camaro","Corvette|Corvette","Impala|Impala"];
} else if(s1.value == "Dodge"){
var optionArray = ["|","Avenger|Avenger","Challenger|Challenger","Charger|Charger"];
} else if(s1.value == "Ford"){
var optionArray = ["|","Mustang|Mustang","Shelby|Shelby"];
}
for(var option in optionArray){
var pair = optionArray[option].split("|");
var newOption = document.createElement("option");
newOption.value = pair[0];
newOption.innerHTML = pair[1];
s2.options.add(newOption);
}
}
if(s2.value == "Camaro" || s2.value=="Corvette"|| s2.value=="Impala"){
var optionArray1 = ["|","Chevy|Chevy"];
} else if(s2.value == "Avenger" || s2.value=="Challenger"|| s2.value=="ImpChargerala"){
var optionArray1 = ["|","Dodge|Dodge"];
} else if(s2.value == "Mustang" || s2.value=="MuShelby"){
var optionArray1 = ["|","Dodge|Dodge"];
}
for(var option in optionArray1){
var pair = optionArray[option].split("|");
var newOption = document.createElement("option");
newOption.value = pair[0];
newOption.innerHTML = pair[1];
s1.options.add(newOption);
}
}
<h2>Choose Your Car</h2>
<hr />
Choose Car Make:
<select id="slct1" name="slct1" onchange="populate(this.id,'slct2')">
<option value=""></option>
<option value="Chevy">Chevy</option>
<option value="Dodge">Dodge</option>
<option value="Ford">Ford</option>
</select>
<hr />
Choose Car Model:
<select id="slct2" name="slct2">
<option value=""></option>
<option value="Camaro">Camaro</option>
<option value="Corvette">Dodge</option>
<option value="Impala">Impala</option>
<option value="Avenger">Avenger</option>
<option value="Corvette">Dodge</option>
<option value="Challenger">Challenger</option>
<option value="Charger">Charger</option>
<option value="Mustang">Mustang</option>
<option value="Shelby">Shelby</option>
</select>
<hr />
Upvotes: 0
Views: 87
Reputation: 4246
Hopefully this should explain a lot. See the comments for why certain parts work the way they do.
This code could be shorter, but I wanted to make it more clear. (For more info about almost any JS feature, MDN is a good source. You can google the feature's name and MDN (like "Arrays MDN") to find results on that site.)
const
// Identifies HTML elements in the DOM that we will need
makesDropdown = document.getElementById("makesDropdown"),
modelsDropdown = document.getElementById("modelsDropdown"),
// Puts Makes and Models in a `cars` object for reference
cars = {
Chevy: ["Camaro", "Corvette", "Impala"],
Dodge: ["Avenger", "Challenger", "Charger"],
Ford: ["Mustang", "Shelby"]
}
;
// Calls the appropriate function when a selection changes
makesDropdown.addEventListener("change", updateModelsDropdown);
modelsDropdown.addEventListener("change", updateMakesDropdown);
// Defines listener functions
function updateModelsDropdown(event){
let
// The "target" of the `change` event is the input that changed
thisMake = event.target.value,
// Gets the array of models from `cars` (If no make is selected, uses all models)
relevantModels = cars[thisMake] || getAllModels();
modelsDropdown.selectedIndex = 0; // Shows the first (blank) option
// The select element's children are the options
let optionElements = modelsDropdown.children;
for(let option of optionElements){
// Uses CSS to hide (or unhide) HTML elements
option.classList.add("hidden");
// Keeps the blank option as well as the ones included in the array
if(relevantModels.includes(option.value) || option.value === ""){
option.classList.remove("hidden");
}
}
}
function updateMakesDropdown(event){
let
thisModel = event.target.value,
relevantMake = "",
// Gets an array of the "keys" for an object
allMakes = Object.keys(cars);
// Loops through the keys and tests each corresponding value (ie, each array of models)
for(let make of allMakes){
let models = cars[make];
// Finds the key whose value includes the selected model
if(models.includes(thisModel)){
// Saves the name of the key so we can select it in the makesDropdown
relevantMake = make;
}
}
let optionElements = makesDropdown.children;
for(let i = 0; i < optionElements.length; i++){
// Finds the index of the matching value
if(relevantMake === optionElements[i].value){
// Selects the option by its index
makesDropdown.selectedIndex = i;
}
}
}
// Defines a helper function
function getAllModels(){
// Gets an array of the "keys" for an object
const makes = Object.keys(cars);
const models = []; // Starts with an empty array to push models into
for(let make of makes){
// `cars[make]` retrieves the value (array of models) for that key
// `...` spreads the array into individual values (models)
// `push` adds each model to the new `models` array
models.push(...cars[make]);
}
return models;
}
.hidden{ display: none; }
<hr />
<h2>Choose Your Car</h2>
<hr /> Choose Car Make:
<select id="makesDropdown">
<option value=""></option>
<option value="Chevy">Chevy</option>
<option value="Dodge">Dodge</option>
<option value="Ford">Ford</option>
</select>
<hr /> Choose Car Model:
<select id="modelsDropdown">
<option value=""></option>
<option value="Camaro">Camaro</option>
<option value="Corvette">Corvette</option>
<option value="Impala">Impala</option>
<option value="Avenger">Avenger</option>
<option value="Challenger">Challenger</option>
<option value="Charger">Charger</option>
<option value="Mustang">Mustang</option>
<option value="Shelby">Shelby</option>
</select>
Note:
Selecting the blank option in the "makesDropdown" automatically resets the "modelsDropdown" so all models are available for the next selection, as one might expect. However, selecting the blank option in the modelsDropdown has no such effect. How would you add this feature to improve user experience?
Upvotes: 1