I am working on a form that has multiple SELECT boxes. When a user selects an option from selectbox1, I need another value of selectbox2 active. Likewise when he selects another value of selectbox2, I need another value of selectbox3 active.
Select Region
<select name='region'>
<option value='nw'>North West</option>
<option value='sw'>South West</option>
<option value='w'>West</option>
</select>
<br />
Select Quarter
<select name='quarter'>
<option value='bda'>Bamenda</option>
<option value='man'>Mankon</option>
<option value='ndop'>Ndop</option>
</select>
<br />
Select Area
<select name='area'>
<option value='ba'>Bambili</option>
<option value='bi'>Bambui</option>
<option value='cc'>CCk</option>
</select>
<br />
When a user selects NORTH WEST, let BAMENDA be selected on the next select box.
Add an onchange function to the select in HTML, and the javascript function below.
function updateSelect(id) {
var index = document.getElementById(id).selectedIndex;
document.getElementById("region").selectedIndex = index;
document.getElementById("quarter").selectedIndex = index;
document.getElementById("area").selectedIndex = index;
}
Select Region
<select name='region' id='region' onchange='updateSelect("region")'>
<option value='nw'>North West</option>
<option value='sw'>South West</option>
<option value='w'>West</option>
</select>
<br />
Select Quarter
<select name='quarter' id='quarter' onchange='updateSelect("quarter")'>
<option value='bda'>Bamenda</option>
<option value='man'>Mankon</option>
<option value='ndop'>Ndop</option>
</select>
<br />
Select Area
<select name='area' id='area' onchange='updateSelect("area")'>
<option value='ba'>Bambili</option>
<option value='bi'>Bambui</option>
<option value='cc'>CCk</option>
</select>
In my opinion you should load that metadata from somewhere on demand, but if you are fine with static arrays, I made an example fiddle that will work just fine:
Cascaded selection example
loadQuarters = function () {
var selectRegion = document.getElementById("selectRegion");
var selectedRegionValue = selectRegion.options[selectRegion.selectedIndex].value;
resetSelectQuarter();
var allowedQuarters = quarters[selectedRegionValue];
allowedQuarters.forEach(function(quarter) {
var selectQuarter = document.getElementById("selectQuarter");
var optionQuarter = document.createElement("option");
optionQuarter.text = quarter.label;
optionQuarter.value = quarter.value;
selectQuarter.add(optionQuarter);
});
}
loadAreas = function () {
var selectQuarter = document.getElementById("selectQuarter");
var selectedQuarterValue = selectQuarter.options[selectQuarter.selectedIndex].value;
resetSelectArea();
var allowedAreas = areas[selectedQuarterValue];
allowedAreas.forEach(function(area) {
var selectArea = document.getElementById("selectArea");
var optionArea = document.createElement("option");
optionArea.text = area.label;
optionArea.value = area.value;
selectArea.add(optionArea);
});
}
resetSelectArea = function() {
var selectArea = document.getElementById("selectArea");
removeOptions(selectArea);
var optionArea = document.createElement("option");
optionArea.text = "Select an area";
optionArea.value = null;
selectArea.add(optionArea);
}
resetSelectQuarter = function() {
var selectQuarter = document.getElementById("selectQuarter");
removeOptions(selectQuarter);
var optionQuarter = document.createElement("option");
optionQuarter.text = "Select a quarter";
optionQuarter.value = null;
selectQuarter.add(optionQuarter);
}
removeOptions = function(selectbox) {
var i;
for(i=selectbox.options.length-1;i>=0;i--)
{
selectbox.remove(i);
}
}
regions = {
"nw": {
value: "nw",
label: "North West"
},
"sw": {
value: "sw",
label: "South West"
},
"w": {
value: "w",
label: "West"
}
};
quarters = {
"nw" : [
{
value: "bda",
label: "Bamenda"
}
],
"sw" : [
{
value: "man",
label: "Mankon"
}
],
"w" : [
{
value: "ndop",
label: "Ndop"
}
]
};
areas = {
"bda" : [
{
value: "ba",
label: "Bambili"
}
],
"man" : [
{
value: "bi",
label: "Bambui"
}
],
"ndop" : [
{
value: "cc",
label: "CCk"
}
]
};
Select Region
<select name='region' id="selectRegion" onChange="loadQuarters()">
<option> Select a region </option>
<option value='nw'>North West</option>
<option value='sw'>South West</option>
<option value='w'>West</option>
</select>
<br />
Select Quarter
<select name='quarter' id="selectQuarter" onChange="loadAreas()">
<option> Select a quarter </option>
</select>
<br />
Select Area
<select name='area' id="selectArea">
<option> Select an area </option>
</select>
<br />
Related
I want to make a select form in HTML that checks that displays a secondary select group if certain options in the first select group are selected
<body>
<form name="Test">
<!-- all the factors to account for when calculating odds-->
<div>
<label>
<select name="FirstList" id="FirstListID">
<option value="1">First option</option>
<option value="2">Second option</option>
<option value="3">Third option</option>
</select><br>
<!-- SecondList would be visible if "1" is selected-->
<label name="SecondList" style="display:none">List for "1":
<select name="SecondListSelect" id="SecondListSelectID">
<option value="3">Placeholder</option>
</select><br>
</label>
<!-- ThirdList would be visible if "2" is selected-->
<label name="ThirdList" style="display:none">List for "2":
<select name="ThirdListSelect" id="ThirdListSelectID">
<option value="4">Placeholder</option>
</select><br>
</label>
<!-- No secondary select form appears if "3" is selected-->
</div>
</form>
</body>
I've tried using AddEventListeners but the code doesn't appear that maintainable since I plan on adding more options in the primary drop down menu so I would need to constantly add what secondary select groups appear based on what primary option is selected. How could I go about coding this in JS?
Give each <label> an identifier tying it to the value for which it should be visible. A data attribute would work. Then, whenever the <select> changes, iterate over all such labels and hide them. Take the .value from the select and use string concatenation to construct a selector for the element with that in the dataset, and then you can select that element and show it.
For example, with labels like
<label data-option=1>
you could have
for (const label of document.querySelectorAll('[data-option]')) {
label.style.display = 'none';
}
document.querySelector(`[data-option=${select.value}]`).style.display = 'block';
inside the change listener.
Store the options of the second <select> element in an object. Make sure the keys match the value attribute value of the options in the first <select>.
Listen for a change event on the first <select>. Whenever a change happens, empty the options of the second <select>, get the new options from the object and create new <option> elements with that data.
Now you have a dynamic <select> element that is easy to scale.
const optionData = {
'1': [
{
label: 'Foo',
value: 'foo',
}
],
'2': [
{
label: 'Bar',
value: 'bar',
},
{
label: 'Baz',
value: 'baz',
}
],
'3': [
{
label: 'Hello',
value: 'hello',
},
{
label: 'World',
value: 'world',
}
]
};
const firstList = document.querySelector('#first-list');
const secondList = document.querySelector('#second-list');
function removeOptions(selectElement) {
for (let i = selectElement.options.length - 1; i >= 0; i--) {
selectElement.remove(i);
}
}
// Update the second `<select>` based on the first's selection.
firstList.addEventListener('change', event => {
const value = event.target.value;
const options = optionData[value];
removeOptions(secondList);
for (const { label, value } of options) {
const option = new Option(label, value);
secondList.add(option);
}
});
<label for="first-list">List One</label>
<select name="first-list" id="first-list">
<option value="" selected disabled>Make a selection</option>
<option value="1">First option</option>
<option value="2">Second option</option>
<option value="3">Third option</option>
</select>
<label for="second-list">List Two</label>
<select name="second-list" id="second-list">
<option value="" selected disabled>No options yet</option>
</select>
You could build the selectors from your js file:
const optionGroups = {
"first": [
{ "text": "for first - 1", "value": 1 }
],
"second": [
{ "text": "for second - 1", "value": 1 },
{ "text": "for second - 2", "value": 2 }
],
"third": [
{ "text": "for third - 1", "value": 1 },
{ "text": "for third - 2", "value": 2 },
{ "text": "for third - 3", "value": 3 }
]
},
mainSelect = document.querySelector('#mainSelect'),
secondarySelect = document.querySelector('#secondarySelect');
async function startWithMainSelect()
{
for (let key of Object.keys(optionGroups))
{
const option = new Option(key);
mainSelect.appendChild(option);
}
onChangeMainSelect();
}
function onChangeMainSelect()
{
while (secondarySelect.firstChild)
secondarySelect.firstChild.remove();
for (let _option of optionGroups[mainSelect.value])
{
const option = new Option(_option.text, _option.value);
secondarySelect.appendChild(option);
}
}
mainSelect.addEventListener('change', onChangeMainSelect);
startWithMainSelect();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>replit</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h4>Main:</h4>
<select id="mainSelect"></select>
<br>
<h4>Secondary:</h4>
<select id="secondarySelect"></select>
<script src="https://replit.com/public/js/replit-badge.js" theme="blue" defer></script>
<script src="script.js"></script>
</body>
</html>
If there were a lot of options, you could move them into a json file and request them from there. Here's an example.
I am a complete beginner making a site for fun/skill development. I saw this code snippet online for cascading dropdowns, but when I run the below code, the form value for "First" comes through as the index number for the value I see in the dropdown (eg. Meals comes through as a 1).
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
let data = [{
item: 'Fruits',
subitems: ['apple', 'banana', 'pineapple', 'watermelon']
},
{
item: 'Meals',
subitems: ['chicken', 'bacon', 'pork', 'beef']
},
{
item: 'Animals',
subitems: ['cat', 'rabbit', 'mouse', 'lion']
},
{
item: 'Brands Laptops',
subitems: ['Dell', 'HP', 'Apple', 'Sony'],
},
];
window.onload = function() {
var itemSel = document.getElementById("first");
var subitemSel = document.getElementById("seconda");
var subitem2Sel = document.getElementById("secondb")
for (var x in data) {
itemSel.options[itemSel.options.length] = new Option(data[x].item, x);
}
itemSel.onchange = function() {
//empty
subitemSel.length = 1;
subitem2Sel.length = 1;
//display correct values
for (var y of data[this.value].subitems) {
subitemSel.options[subitemSel.options.length] = new Option(y, y);
}
for (var z of data[this.value].subitems) {
subitem2Sel.options[subitem2Sel.options.length] = new Option(z, z);
}
}
}
</script>
</head>
<body>
<h1>Cascading Dropdown Example</h1>
<form name="form1" id="form1" action="/action_page.php">
First:
<select name="first" id="first">
<option value="" selected="selected">Select type</option>
</select>
<br><br> Second A:
<select name="seconda" id="seconda">
<option value="" selected="selected">Please select first</option>
</select>
<br><br> Second B:
<select name="secondb" id="secondb">
<option value="" selected="selected">Please select first</option>
</select>
<br><br>
<input type="submit" value="Submit">
</form>
</body>
I know how to alter the code to get the value of First to come through as the text, but that then messes up the cascading dropdowns. How can I get the form, upon hitting submit, to give me the text value from "First" and not the index number of whatever is selected?
Say I want an object with this format
var optgroups = [
{
name: "Cat1",
options: [
{ text: "item1", value: "1" },
{ text: "item4", value: "4" },
],
},
{ name: "Cat2", options: [{ text: "item2", value: "2" }] },
{ name: "Cat3", options: [{ text: "item3", value: "3" }] },
];
And I want to create it based on what's already populated in a select element in a form
<select>
<optgroup label="Cat1">
<option value="1">item1</option>
<option value="4">item4</option>
</optgroup>
<optgroup label="Cat2">
<option value="2">item2</option>
</optgroup>
<optgroup label="Cat3">
<option value="3">item3</option>
</optgroup>
</select>
What JavaScript code (jQuery is also an option) would achieve such an object?
This is an old code base so things like React/Vue are not an option.
You can use document.querySelectorAll to get all the <optgroup> elements to loop over and use it again to find all the options.
const optgroups = [];
document.querySelectorAll("#mySelect > optgroup").forEach(group=>{
const obj = {name: group.label, options: []};
group.querySelectorAll('option').forEach(option=>{
obj.options.push({text: option.textContent, value: option.value});
});
optgroups.push(obj);
});
console.log(optgroups);
<select id="mySelect">
<optgroup label="Cat1">
<option value="1">item1</option>
<option value="4">item4</option>
</optgroup>
<optgroup label="Cat2">
<option value="2">item2</option>
</optgroup>
<optgroup label="Cat3">
<option value="3">item3</option>
</optgroup>
</select>
Here's what I ended up using thanks to #hev1
const optgroups = [
...document.querySelectorAll("#mySelect > optgroup"),
].map((group) => ({
name: group.label,
options: [...group.querySelectorAll("option")].map((opt) => ({
text: opt.textContent,
value: opt.value,
})),
}));
I want to get the JSON from an array with this format
[
{
"title": "Name"
},
{
"title": "Phone"
},
{
"title": "Parent Phone"
},
{
"title": "Street"
}
]
I tried this code:
var favorite = new Array();
$.each($("#db_fields"), function() {
var field = {
'title': $(this).val()
};
favorite.push(field);
});
var myJsonString = JSON.stringify(favorite);
alert(myJsonString);
$("#db_fields") is a select (Bootstrap-select), it's an array of string
<select class="form-control" name="db_fields[]" id="db_fields" data-live-search="true" multiple >
<option value="Arabic Name"> Arabic Name</option>
<option value="Building"> Building</option>
</select>
but I got this result
[{"title":["Arabic Name","Phone","Building","Nationality"]}]
Iterate through the options of the select ("#db_fields > option") tag:
var favorite = [];
$.each($("#db_fields > option"), function(){
let field = {
'title': this.value
};
favorite.push(field);
});
var myJsonString = JSON.stringify(favorite);
console.log(myJsonString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="form-control" name="db_fields[]" id="db_fields" data-live-search="true" multiple >
<option value="Arabic Name"> Arabic Name</option>
<option value="Building"> Building</option>
</select>
How do I only display certain options depending on the value in a select tag?
function key(id){
var selectValue = document.getElementById('names').value
= document.carmakes.cars.selectedIndex
var selectOption = $("#names option:selected").val();
}
<select size='5' name='carmakes' onchange='key(id)'>
<option selected='selected' value="-1">Car makes</option>
<option>BMW</option>
<option>Audi</option>
</select>
<select required='required' size='5' type='text' id='names'>
<option selected="selected" value="0" >Car names</option>
<option value="1">X5</option>
<option value="2">Q5</option>
check this: http://www.sanwebe.com/2013/05/select-box-change-dependent-options-dynamically
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8' />
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
//let's create arrays
var chocolates = [
{display: "Dark chocolate", value: "dark-chocolate" },
{display: "Milk chocolate", value: "milk-chocolate" },
{display: "White chocolate", value: "white-chocolate" },
{display: "Gianduja chocolate", value: "gianduja-chocolate" }];
var vegetables = [
{display: "Broccoli", value: "broccoli" },
{display: "Cabbage", value: "cabbage" },
{display: "Carrot", value: "carrot" },
{display: "Cauliflower", value: "cauliflower" }];
var icecreams = [
{display: "Frozen yogurt", value: "frozen-yogurt" },
{display: "Booza", value: "booza" },
{display: "Frozen yogurt", value: "frozen-yogurt" },
{display: "Ice milk", value: "ice-milk" }];
//If parent option is changed
$("#parent_selection").change(function() {
var parent = $(this).val(); //get option value from parent
switch(parent){ //using switch compare selected option and populate child
case 'chocolates':
list(chocolates);
break;
case 'vegetables':
list(vegetables);
break;
case 'icecreams':
list(icecreams);
break;
default: //default child option is blank
$("#child_selection").html('');
break;
}
});
//function to populate child select box
function list(array_list)
{
$("#child_selection").html(""); //reset child options
$(array_list).each(function (i) { //populate child options
$("#child_selection").append("<option value=\""+array_list[i].value+"\">"+array_list[i].display+"</option>");
});
}
});
</script>
</head>
<body>
<div class="wrapper">
Category : <select name="parent_selection" id="parent_selection">
<option value="">-- Please Select --</option>
<option value="chocolates">Chocolates</option>
<option value="vegetables">Vegetables</option>
<option value="icecreams">Ice cream</option>
</select>
<select name="child_selection" id="child_selection">
</select>
</div>
</body>
</html>
or this: http://simpleweb.github.io/jquery-dependent-selects/
A working example: http://jsfiddle.net/20omnz2c/
$('#carmakes').on('change', function () {
var selected = $(this).val().toLowerCase();
if (selected != '0') {
$('#names').show();
$('#names option').hide(); //hide all options initially
$('#names option:eq(0)').show(); //show the first option
$('#names option.' + selected).show(); //show options with the right class
} else {
$('#names').hide();
$('#names option').hide();
}
});