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?
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 don't know what else to do. I want to Create a set of cascading select lists, where the selection of an item from the first list determines which list to display in the second list.I would like to know how to do it if someone could give me a clearer explanation please
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("item");
var subitemSel = document.getElementById("subitems");
for (var x in data) {
itemSel.options[itemSel.options.length] = new Option(x, x);
}
itemSel.onchange = function() {
//empty
subitemSel.length = 1;
//display correct values
for (var y in itemObject[this.value]) {
subitemSel.options[subitemSel.options.length] = new Option(y, y);
}
}
}
<!DOCTYPE html>
<html lang="en-CA">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script defer type="module" src="./js/main.js"></script>
</head>
<body>
<header>
<h1>Moshe Brito</h1>
<h2>41088278</h2>
</header>
<main>
<!-- content will be built here by javascript -->
<div>
<label for="first">First List</label>
<select id="first" name="first">
<option value="" selected="selected">Please select first</option>
</select>
</div>
<div>
<label for="second">Second List</label>
<select id="second" name="second">
<option value="" selected="selected">Please select second</option>
</select>
</div>
</main>
</body>
</html>
You use invalid value for getElementById().
Those must refer to real HTML id attribute but you refer all of them to not exists.
The result in console showing error TypeError: itemSel is null.
The select text in Option() is in first argument. See reference.
If you use just x in data then x will be index number. It is okay to use it in value attribute but select text should be readable. So, it should be data[x].item in the first Option() argument.
Now go to inside the onchange event. You use undeclared itemObject variable and when first select box has been changed, it will be error here.
This variable must be replace with data[this.value].subitems if you want to list sub items property.
Full code.
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("second");
for (var x in data) {
itemSel.options[itemSel.options.length] = new Option(data[x].item, x);
}
itemSel.onchange = function() {
//empty
subitemSel.length = 1;
//display correct values
for (var y of data[this.value].subitems) {
subitemSel.options[subitemSel.options.length] = new Option(y, y);
}
}
}
<header>
<h1>Moshe Brito</h1>
<h2>41088278</h2>
</header>
<main>
<!-- content will be built here by javascript -->
<div>
<label for="first">First List</label>
<select id="first" name="first">
<option value="" selected="selected">Please select first</option>
</select>
</div>
<div>
<label for="second">Second List</label>
<select id="second" name="second">
<option value="" selected="selected">Please select second</option>
</select>
</div>
</main>
I have form that select User ID among Users.
<select>
<option value="">Tabs User</option>
<option value="ID3357">ID3357</option>
<option value="ID2695">ID2695</option>
<option value="ID1072">ID1072</option>
<option value="ID1306">ID1306</option>
<option value="ID2702">ID2702</option>
The First name of the users:
ID2695 Jacob
ID1072 Moe
ID1306 sara
ID2702 Sam
how to show the Firstname of ID below the form, when the enduser pick the ID in form.
this code might help,
<!DOCTYPE html>
<html>
<body>
<h1 id="name"></h1>
<select onchange="getUser(this.value)">
<option disabled selected value>-</option>
<option value="ID3357">ID3357</option>
<option value="ID2695">ID2695</option>
<option value="ID1072">ID1072</option>
<option value="ID1306">ID1306</option>
<option value="ID2702">ID2702</option>
</select>
<script type="text/javascript">
var users = [
{ id: "ID2695", firstName: "Jacob" },
{ id: "ID1072", firstName: "Moe" },
{ id: "ID1306", firstName: "Sara" },
{ id: "ID2702", firstName: "Sam" },
{ id: "ID3357", firstName: "Someone" }
];
function getUser(uid) {
var [{ firstName }] = users.filter(({id}) => id === uid);
document.getElementById("name").textContent = firstName;
}
</script>
</body>
</html>
Explanation: The users are hard-coded into the js as objects with and id and username. As soon as somebody picks a value from the dropdown, js gets the value from the dropdown input and filters the array + selects the firstName from the returned array of an object. Then it displays that into the h1. As simple as that.
I have this models:
var data = [
{
id: 1,
level:1,
name:"X1",
subChildren:[{
id:3,
level:2,
name:"X1-1",
subChildren:[...]
}]
},
{
id: 2,
level:1,
name:"X2",
subChildren:[{
id:4,
level:2,
name:"X2-2",
subChildren:[...]
}]
}....];
var levels=[{ level:1,.. },{ level:2,.. },...];
What I want is to show the data in html <select> element, and cascade them depending on the selected parent. i.e:
level 1:
<select>
<option>X1</option>
<option>X2</option>
</select>
-
level 2: (subChildren)
<select>
<option>X1-1</option>
</select>
-
level 3 (sub subChildren)
<select>
<option>X1-1-1</option>
</select>
This is only a non-functional demonstration for what I want to show, when you choose one of the parents it will cascade the next <select> which should be the next level (and contains the sub children) and so on..
The problem is I don't know the number of levels or the number of parents or subChildren, it's all dynamic, and don't know how to do this without writing a lot of native code.
The whole idea is I want to iterate over levels array and create the <select> tags.
This solution works only if you know the maximum number of subchildren you will encounter.Please check the plunkr Plnkr
// Code goes here
var app = angular.module('Dropdown', []).controller('DpdController', function($scope) {
$scope.data = [{
id: 1,
level: 1,
name: "X1",
subChildren: [{
id: 3,
level: 2,
name: "X1-1",
subChildren: [{
id: 4,
level: 3,
name: "X1-2"
}]
}]
}];
$scope.logValue = function(value) {
console.log(value);
}
});
<!DOCTYPE html>
<html ng-app="Dropdown">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.2/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="DpdController">
<select name="repeatSelect" id="repeatSelect" ng-model="selectedValue" ng-change="logValue(selectedValue)" ng-options="option.name for option in data">
</select>
<span ng-if='selectedValue'>
<select name="repeatSelect1" id="repeatSelect1" ng-model="selectedValue1"
ng-change="logValue(selectedValue1)"
ng-options="option.name for option in selectedValue.subChildren">
</select>
</span>
</body>
</html>
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 />