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 have 3 dependent JSON files that are related together, which are countries.json, states.json and cities.json and i want to fill 3 dropdowns select box with those json files i have. For the first time i select a country in the first dropdown, i see its states in the second dropdown but the problem comes when i select another country, its states come with the states of the previous selected country.
$(document).ready(function(){
var countryOptions = '';
var stateOptions = '';
var cityOptions = '';
$.getJSON('countries.json', function(data){
countryOptions += '<option value="">Select country</option>';
$.each(data, function(key, country){
countryOptions += '<option value="'+country.id+'">'+country.name+'</option>';
});
$('#country').html(countryOptions);
});
$(document).on('change', '#country', function(){
var country_id = $(this).val();
if(country_id != '')
{
$.getJSON('states.json', function(data){
stateOptions += '<option value="">Select state</option>';
$.each(data, function(key, state){
if(country_id == state.country_id)
{
stateOptions += '<option value="'+state.id+'">'+state.name+'</option>';
}
});
$('#state').html(stateOptions);
});
}
else
{
$('#state').html('<option value="">Select state</option>');
$('#city').html('<option value="">Select city</option>');
}
});
$(document).on('change', '#state', function(){
var state_id = $(this).val();
if(state_id != '')
{
$.getJSON('cities.json', function(data){
cityOptions += '<option value="">Select city</option>';
$.each(data, function(key, city){
if(state_id == city.state_id)
{
cityOptions += '<option value="'+city.id+'">'+city.name+'</option>';
}
});
$('#city').html(cityOptions);
});
}
else
{
$('#city').html('<option value="">Select city</option>');
}
});
});
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container" style="width:600px;">
<h2 align="center">JSON - Dynamic Dependent Dropdown List using Jquery and Ajax</h2><br /><br />
<select name="country" id="country" class="form-control input-lg">
<option value="">Select country</option>
</select>
<br />
<select name="state" id="state" class="form-control input-lg">
<option value="">Select state</option>
</select>
<br />
<select name="city" id="city" class="form-control input-lg">
<option value="">Select city</option>
</select>
</div>
//countries.json
[
{
"id":"1",
"name":"USA"
},
{
"id":"2",
"name":"Canada"
},
{
"id":"3",
"name":"Australia"
}
]
//states.json
[
{
"id":"4",
"name":"New York",
"country_id":"1"
},
{
"id":"5",
"name":"Alabama",
"country_id":"1"
},
{
"id":"6",
"name":"California",
"country_id":"1"
},
{
"id":"7",
"name":"Ontario",
"country_id":"2"
},
{
"id":"8",
"name":"British Columbia",
"country_id":"2"
},
{
"id":"9",
"name":"New South Wales",
"country_id":"3"
},
{
"id":"10",
"name":"Queensland",
"country_id":"3"
}
]
//cities.json
[
{
"id":"11",
"name":"New York city",
"state_id":"4"
},
{
"id":"12",
"name":"Buffalo",
"state_id":"4"
},
{
"id":"13",
"name":"Albany",
"state_id":"4"
},
{
"id":"14",
"name":"Birmingham",
"state_id":"5"
},
{
"id":"15",
"name":"Montgomery",
"state_id":"5"
},
{
"id":"16",
"name":"Huntsville",
"state_id":"5"
},
{
"id":"17",
"name":"Los Angeles",
"state_id":"6"
},
{
"id":"18",
"name":"San Francisco",
"state_id":"6"
},
{
"id":"19",
"name":"San Diego",
"state_id":"6"
},
{
"id":"20",
"name":"Toronto",
"state_id":"7"
},
{
"id":"21",
"name":"Ottawa",
"state_id":"7"
},
{
"id":"22",
"name":"Vancouver",
"state_id":"8"
},
{
"id":"23",
"name":"Victoria",
"state_id":"8"
},
{
"id":"24",
"name":"Sydney",
"state_id":"9"
},
{
"id":"25",
"name":"Newcastle",
"state_id":"9"
},
{
"id":"26",
"name":"City of Brisbane",
"state_id":"10"
},
{
"id":"27",
"name":"Gold Coast",
"state_id":"10"
}
]
How to solve this problem? i have tried so far, i think the error is in the JQuery loop function $.each(data, function(key, state){});
$.getJSON('states.json', function(data){
stateOptions +=
This is appending to your existing data when you get new data. Change it to this:
$.getJSON('states.json', function(data){
stateOptions =
$(document).ready(function(){
var countryOptions = '';
var stateOptions = '';
var cityOptions = '';
$.getJSON('countries.json', function(data){
countryOptions += '<option value="">Select country</option>';
$.each(data, function(key, country){
countryOptions += '<option value="'+country.id+'">'+country.name+'</option>';
});
$('#country').html(countryOptions);
});
$(document).on('change', '#country', function(){
var country_id = $(this).val();
if(country_id != '')
{
$.getJSON('states.json', function(data){
stateOptions = '<option value="">Select state</option>';
$.each(data, function(key, state){
if(country_id == state.country_id)
{
stateOptions += '<option value="'+state.id+'">'+state.name+'</option>';
}
});
$('#state').html(stateOptions);
});
}
else
{
$('#state').html('<option value="">Select state</option>');
$('#city').html('<option value="">Select city</option>');
}
});
$(document).on('change', '#state', function(){
var state_id = $(this).val();
if(state_id != '')
{
$.getJSON('cities.json', function(data){
cityOptions += '<option value="">Select city</option>';
$.each(data, function(key, city){
if(state_id == city.state_id)
{
cityOptions += '<option value="'+city.id+'">'+city.name+'</option>';
}
});
$('#city').html(cityOptions);
});
}
else
{
$('#city').html('<option value="">Select city</option>');
}
});
});
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container" style="width:600px;">
<h2 align="center">JSON - Dynamic Dependent Dropdown List using Jquery and Ajax</h2><br /><br />
<select name="country" id="country" class="form-control input-lg">
<option value="">Select country</option>
</select>
<br />
<select name="state" id="state" class="form-control input-lg">
<option value="">Select state</option>
</select>
<br />
<select name="city" id="city" class="form-control input-lg">
<option value="">Select city</option>
</select>
</div>
Note The code snippet is just for OPs sake. It won't run because it utilizes Get requests.
I have 3 select2 fields where I want to populate them using AJAX from API. My question is, how can I populate the first select field option directly from API and then the second field option is populated also by API but based on my selection(s) from the first select field, same goes for the third one.
For example, below are my code & data:
API
[
{
"id": 1,
"project_type": "tv",
"project_stage": "new",
"project_name": "Project A"
},
{
"id": 2,
"project_type": "game",
"project_stage": "completed",
"project_name": "Project B"
},
{
"id": 3,
"project_type": "game",
"project_stage": "new",
"project_name": "Project C"
},
{
"id": 4,
"project_stage": "completed",
"project_type": "film",
"project_name": "Project D"
}
]
HTML
<div class="group">
<select class="project_type" id="project_type" multiple="multiple">
<option value=""></option>
</select>
<select class="project_status" id="project_status" multiple="multiple"">
<option value=""></option>
</select>
<select class="project_select" id="project_select" multiple="multiple">
<option value=""></option>
</select>
</div>
Javascript
$('#project_type').select2({placeholder: "Select project type",});
$('#project_status').select2({placeholder: "Select project Status",});
$('#project_select').select2({placeholder: "Select project",});
Expected Result :
Now the project_type select field wield populate all of the project type as option and say we select "game" then the project_status option would be :
<select class="project_status" id="project_status" multiple="multiple"">
<option value="completed">Completed</option>
<option value="new">New</option>
</select>
and if we select completed, the third filter would be:
<select class="project_select" id="project_select" multiple="multiple">
<option value="Project B">Project B</option>
</select>
I populated this from jinja2 before and its not dynamic, any help is much appreciated thanks.
UPDATE :
below is my current code, for odd reason even for the first filter, its not populating the option even though I'm getting the data :
$('#project_type').select2({
placeholder: "Select project type",
ajax: {
url: '/api/filter/',
delay: 250,
type: 'GET',
data: function (params) {
var query = {
search: params.term,
type: 'public'
}
return query
},
processResults: function (data) {
var data1 = $.map(data, function (obj, idx) {
console.log(obj.project_type);
return obj;
});
console.log("processResults2:", data1);
return {
results: data1,
};
}
}
});
Here is a snippet implementing Select2 Ajax populate (in cascade):
var data = [
{
"id": 1,
"project_type": "tv",
"project_stage": "new",
"project_name": "Project A"
},
{
"id": 2,
"project_type": "game",
"project_stage": "completed",
"project_name": "Project B"
},
{
"id": 3,
"project_type": "game",
"project_stage": "new",
"project_name": "Project C"
},
{
"id": 4,
"project_stage": "completed",
"project_type": "film",
"project_name": "Project D"
}
];
sel_type();
$('#project_status').select2({placeholder: ""});
$('#project_select').select2({ placeholder: ""});
function sel_type() {
$('#project_type').select2({
placeholder: "Select project type",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var grouped = groupBy(data.data, 'project_type');
var data1 = [], i = 0;
for (var k in grouped) {
data1.push({"id": i++, "text": k})
}
return {
results: data1,
};
}
}
});
$('#project_type').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
sel_status(data.text);
});
}
function sel_status(type) {
$('#project_status').select2({
placeholder: "Select project status",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var data1 = $.map(data.data, function (obj, idx) {
if (obj.project_type==type)
return obj;
});
var grouped = groupBy(data1, 'project_stage');
var data1 = [], i = 0;
for (var k in grouped) {
data1.push({"id": i++, "text": k})
}
return {
results: data1,
};
}
}
});
$('#project_status').on('select2:select', function (e) {
var data = e.params.data;
console.log(data);
sel_proj(type, data.text);
});
}
function sel_proj(type, status) {
$('#project_select').select2({
placeholder: "Select project",
ajax: {
type: "POST",
url: '/echo/json/',
data: function(params){
var query={
message:params.term,
data: data
}
return { json: JSON.stringify( query ) }
},
processResults: function (data) {
var data1 = $.map(data.data, function (obj, idx) {
if (obj.project_type==type && obj.project_stage==status) {
obj.id = obj.id || idx;
obj.text = obj.project_name;
return obj;
}
});
return {
results: data1,
};
}
}
});
}
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
select {
width:200px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/>
<div class="group">
<select class="project_type" id="project_type" multiple="multiple">
<option value=""></option>
</select>
<br/>
<select class="project_status" id="project_status" multiple="multiple">
<option value=""></option>
</select>
<br/>
<select class="project_select" id="project_select" multiple="multiple">
<option value=""></option>
</select>
</div>
but because of the Ajax request it does not work here in StackOverflow.
A working version (using JsFiddle echo) is here: https://jsfiddle.net/beaver71/4nq62nqo/
P.S.: you have to change the uri in Ajax request to yours, and remove POST of data.
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 />
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();
}
});