Javascript Chain Dropdown Select - javascript

I know that there are a lot of this questions being posted online but I still have difficulty finding what I need.
Currently I have found something that is doing 3 chained dropdown selection maximum. I needed to have 4 and I have tried editing the script but it's not working.
Below is the code that I have edited, is there anything wrong with my code?
<html>
<head>
<script type="text/javascript">
// State lists
var states = new Array();
states[0] = new Array('Alberta','British Columbia','Ontario');
states[1] = new Array('Baja California','Chihuahua','Jalisco');
states[2] = new Array('California','Florida','New York');
// Province lists
var provinces = new Array();
provinces[0] = new Array();
provinces[0][0] = new Array("Province1", "Province2");
// City lists
var cities = new Array();
cities[0][0] = new Array();
cities[0][0][0] = new Array('Edmonton','Calgary');
cities[0][0][1] = new Array('Victoria','Vancouver');
function setStates(){
cntrySel = document.getElementById('country');
stateList = states[cntrySel.selectedIndex];
changeSelect('state', stateList);
setProvinces();
}
function setProvinces(){
cntrySel = document.getElementById('country');
stateSel = document.getElementById('state');
provinceList = provinces[cntrySel.selectedIndex][stateSel.selectedIndex];
changeSelect('province', provinceList);
setCities();
}
function setCities(){
cntrySel = document.getElementById('country');
stateSel = document.getElementById('state');
provinceList = document.getElementById('province');
cityList = cities[cntrySel.selectedIndex][stateSel.selectedIndex][provinceList.selectedIndex];
changeSelect('city_town_district', cityList);
}
function changeSelect(fieldID, newList) {
selectField = document.getElementById(fieldID);
selectField.options.length = 0;
for (i=0; i<newList.length; i++) {
selectField.options[selectField.length] = new Option(newList[i], newList[i], newList[i]);
}
}
</script>
</head>
<body onload="setStates();">
<form name="test">
Country:
<select name="country" id="country" onchange="setStates();">
<option value="Canada">Canada</option>
<option value="Mexico">Mexico</option>
<option value="United States">United States</option>
</select>
<br>
State:
<select name="state" id="state" onchange="setProvinces();">
<option value="">Please select a State</option>
</select>
<br>
Province:
<select name="province" id="province" onchange="setCities();">
<option value="">Please select a Province</option>
</select>
<br>
City:
<select name="city_town_district" id="city_town_district">
<option value="">Please select a City</option>
</select>
</form>
</body>
</html>
Any help will be much appreciated! Thanks in advance!

Old question, one answer and everybody have to do this sometimes.
The year is 2018 and I find a easy way to do this. Easy to add, edit and receive data from server. Bye!
JSFiddle
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<select name="slc1" id="slc1" onchange="_1sel();"></select>
<select name="slc2" id="slc2" onchange="_2sel();"></select>
<select name="slc3" id="slc3" onchange="_3sel();"></select>
<select name="slc4" id="slc4"></select>
<script>
//just call the method when the select change
var slc1 = document.getElementById("slc1");
var slc2 = document.getElementById("slc2");
var slc3 = document.getElementById("slc3");
var slc4 = document.getElementById("slc4");
var dataObj = {//is a valid json
"brazil": {
"sp": {
"sp1": ["sp1A", "sp1B"],
"sp2": ["sp2A"]
},
"mg": {
"mg1": ["mg1A", "mg1B"],
"mg2": ["mg2A", "mg1B"]
},
"rj": {
"rj1": ["rj1A", "rj1B", "rj1C"],
"rj2": ["rj2A", "rj1B"]
}
},
"usa": {
"ny": {
"ny1": ["ny1A","ny1B","ny1C"],
"ny2": ["ny2A"]
},
"tx": {
"tx1": ["tx1A"]
}
},
"uk": {
"ld": {
"ld1": ["ld1A","ld1B","ld1C"],
"ld2": ["ld2A"]
},
"hm": {
"hm1": ["hm1A", "hm1B"]
}
}
}
let ctrs = Object.keys(dataObj);//countries - Object.keys return an array
cmo(ctrs, slc1);//push values to select one
_1sel();//call the first method of chain
//slc1.value = "usa"
//slc1.dispatchEvent(new Event('change'));
function _1sel() {
slc2.innerHTML = "";//clear the target select
let cities = Object.keys(dataObj[slc1.value]);//get the cities from country as array
cmo(cities, slc2);//push values to select two
_2sel();//call the second method of chain
}
function _2sel() {
slc3.innerHTML = "";//clear
let zones = Object.keys(dataObj[slc1.value][slc2.value]);//get the zones from country and city as array
cmo(zones, slc3);//push values to select three
_3sel();//call the third method of chain
}
function _3sel() {
slc4.innerHTML = "";//clear
let staffs = dataObj[slc1.value][slc2.value][slc3.value];//no Obj.keys here, just get the array of values
cmo(staffs, slc4);//push values to select four
}
function cmo(arr, s) {//create options and add to select
arr.forEach(o => {
let opt = document.createElement("option");
opt.value = o;
opt.innerHTML = o;
s.add(opt);
});
}
</script>
</body>
</html>

This is not perfect by any means but it should get you going. Instead of having unrelated arrays I suggest you use some object oriented principles. I've chosen to use JSON to describe the relationships in the data. The other advantage to using JSON is that many server side languages have JSON serializers available to them.
I have kept as much of your code as possible so there is some familiarity for you. However inline event handling is not considered best practice these days. You should look at Event Listeners/Handlers instead. Or if it was me I would be using jQuery as it irons out much of the cross browser issues you can come across.
/*Use JSON to describe data and its relationship*/
var countries = [{
"CountryName": "Canada",
"States": [{
"StateName": "British Columbia",
"Provences": [{
"ProvenceName": "BC P1",
"Cities": ["Vancouver"]
}, {
"ProvenceName": "BC P2",
"Cities": ["Whistler"]
}]
}, {
"StateName": "Ontario ",
"Provences": [{
"ProvenceName": "Ot 1",
"Cities": ["Ontario"]
}, {
"ProvenceName": "Ot 2",
"Cities": ["Toronto"]
}]
}]
}, {
"CountryName": "United States",
"States": [{
"StateName": "New York",
"Provences": [{
"ProvenceName": "NY P1",
"Cities": ["New York", "New Jersy"]
}, {
"ProvenceName": "NY P2",
"Cities": ["Buffalo"]
}]
}, {
"StateName": "California",
"Provences": [{
"ProvenceName": "South",
"Cities": ["Los Angeles", "San Dieago"]
}, {
"ProvenceName": "North",
"Cities": ["San Francisco"]
}]
}]
}];
var selectedCountry;
var selectedState;
var selectedProvence;
var stateList = document.getElementById("state");
var provenceList = document.getElementById("province");
var cityList = document.getElementById("city_town_district");
function setStates(selectedIndex) {
selectedCountry = countries[selectedIndex];
stateList.options.length = 0;
for (i = 0; i < selectedCountry.States.length; i++) {
stateList.options[stateList.length] = new Option(selectedCountry.States[i].StateName, selectedCountry.States[i].StateName, selectedCountry.States[i].StateName);
}
setProvinces(0);
}
function setProvinces(selectedIndex) {
selectedState = selectedCountry.States[selectedIndex];
console.log(selectedState)
provenceList.options.length = 0;
for (i = 0; i < selectedState.Provences.length; i++) {
provenceList.options[provenceList.length] = new Option(selectedState.Provences[i].ProvenceName, selectedState.Provences[i].ProvenceName, selectedState.Provences[i].ProvenceName);
}
setCities(0);
}
function setCities(selectedIndex) {
selectedProvence = selectedState.Provences[selectedIndex];
cityList.options.length = 0;
for (i = 0; i < selectedProvence.Cities.length; i++) {
cityList.options[cityList.length] = new Option(selectedProvence.Cities[i], selectedProvence.Cities[i], selectedProvence.Cities[i]);
}
}
Country:
<select name="country" id="country" onchange="setStates(this.selectedIndex);">
<option value="Canada">Canada</option>
<option value="United States">United States</option>
</select>
<br>State:
<select name="state" id="state" onchange="setProvinces(this.selectedIndex);">
<option value="">Please select a State</option>
</select>
<br>Province:
<select name="province" id="province" onchange="setCities(this.selectedIndex);">
<option value="">Please select a Province</option>
</select>
<br>City:
<select name="city_town_district" id="city_town_district">
<option value="">Please select a City</option>
</select>

Related

3 level multiple cascanding dropdown using Array

I am trying to create a 3 level dropdown with data, but the second and third dropdowns still show the data as a whole. How to have the second and third dropdown filter data based on related data?
var json = [{
"country": "USA",
"state": "LOS ANGELES",
"city": "LOS ANGELES"
},
{
"country": "USA",
"state": "LOS ANGELES",
"city": "LOS ANGELES 2"
},
{
"country": "USA",
"state": "New York",
"city": "New York",
},
{
"country": "USA",
"state": "New York",
"city": "New York 2",
},
{
"country": "CANADA",
"state": "British Columbia",
"city": "Vancovour",
}
];
for (i = 0; i < json.length; i++) {
$("#country").append("<option value=" + json[i]["country"] + ">" + json[i]["country"] + "</option>");
$("#state").append("<option value=" + json[i]["country"] + ">" + json[i]["state"] + "</option>");
$("#city").append("<option value=" + json[i]["country"] + ">" + json[i]["city"] + "</option>");
}
$("#state").change(function() {
$("#country")[0].selectedIndex = $(this)[0].selectedIndex
$("##city")[0].selectedIndex = $(this)[0].selectedIndex
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="myform" id="myForm">
<select name="opttwo" id="country" size="1">
<option value="" selected="selected">Please select state </option>
</select>
<br>
<br>
<select name="optone" id="state" size="1">
<option value="" selected="selected">Please Select country first</option>
</select>
<br>
<br>
<select name="optthree" id="city" size="1">
<option value="" selected="selected">Please select country first</option>
</select>
</form>
I have tried to make it like this. what should I add?
var json = [{
"country": "USA",
"state": "LOS ANGELES",
"city": "LOS ANGELES"
},
{
"country": "USA",
"state": "LOS ANGELES",
"city": "LOS ANGELES 2"
},
{
"country": "USA",
"state": "New York",
"city": "New York",
},
{
"country": "USA",
"state": "New York",
"city": "New York 2",
},
{
"country": "CANADA",
"state": "British Columbia",
"city": "Vancovour",
}
];
function addElementsFor(c, v, index) {
var tracker = [];
for (var i = 0, o; o = json[i]; i++) {
if (!!v && !!index && o[v] !== json[index][v]) {
continue;
}
if (tracker.indexOf(o[c.id]) !== -1) {
continue;
}
tracker.push(o[c.id]);
var option = document.createElement('option');
option.value = i;
option.innerText = o[c.id];
c.appendChild(option);
}
return c
}
function populateSubCategory(c, v, index) {
var state = document.getElementById(c);
state.disabled = false;
while (state.firstChild) state.firstChild.remove();
var option = document.createElement('option');
option.value = -1;
option.innerText = '----';
state.appendChild(option);
if (index * 1 < 0) return;
return addElementsFor(state, v, index);
}
window.addEventListener('load', function() {
addElementsFor(document.getElementById('country')).addEventListener('change', function(ev) {
populateSubCategory('state', ev.target.id, ev.target.value).addEventListener('change', function(ev) {
populateSubCategory('city', ev.target.id, ev.target.value).addEventListener('change', function(ev) {
if (ev.target.value * 1 < 0) {
return;
}
var country = document.getElementById('country');
var state = document.getElementById('state');
var city = ev.target;
if (json.hasOwnProperty(country.value) && json.hasOwnProperty(state.value) && json.hasOwnProperty(city.value)) {
console.log('country: %s state: %s city: %s', json[country.value]['country'], json[state.value]['state'], json[city.value]['city']);
}
})
})
})
});
<form name="myform" id="myForm">
<select name="opttwo" id="country" size="1">
<option value="-1" selected="selected">Please select state </option>
</select>
<br>
<br>
<select name="optone" id="state" size="1">
<option value="-1" selected="selected">Please Select country first</option>
</select>
<br>
<br>
<select name="optthree" id="city" size="1">
<option value="-1" selected="selected">Please select country first</option>
</select>
</form>
You need to check if there is already a select element with the same content before adding it again or you will end up with duplicates.
Check this thread: https://stackoverflow.com/a/9791018/5211055

How to update json value with dropdown list

Can anyone teach me how can I update json value using the the dropdown list.
In JavaScript
HTML:
<select id="currency" onchange="getSelectValue();">
<option value="Singapore Dollar">Singapore Dollar</option>
<option value="USD">USD</option>
<option value="Malaysia Riggit">Malaysia Riggit</option>
</select>
JSON :
{
"products": [
{
"name": "Apple",
"price": "2.50",
"code": "SGD"
},
{
"name": "Orange",
"price": "2.50",
"code": "SGD"
}
]
}
You can create a select in javascript like this, focus on the <script />
<!DOCTYPE html>
<html lang="en">
<head>
<title>Javascript - Select</title>
</head>
<body>
<div id="main"></div>
</body>
<script>
const {products} = JSON.parse('{ "products": [ { "name": "Apple", "price": "2.50", "code": "SGD" }, { "name": "Orange", "price": "2.50", "code": "SGD" } ] }');
const select = document.createElement("select");
select.id = 'currency';
select.onchange = ({target: {value}}) => console.log(value);
products.forEach(({code, name}) => {
const option = document.createElement("option");
option.label = name;
option.value = code;
select.appendChild(option);
});
const main = document.getElementById('main');
main.appendChild(select);
</script>
</html>
EDIT:
Add the "value" as a param of the function
<select id="currency" onchange="getSelectValue(value)">
<option value="SGD">Singapore Dollar</option>
<option value="USD">USD</option>
<option value="MR">Malaysia Riggit</option>
</select>
and the function definition should look like this:
const getSelectValue = (selectedValue) => {
console.log(selectedValue);
// Your code...
};
Here is the code sample.
var json=JSON.parse( "Your json which you mentioned above");
var products= json.products;
string selectlist="";
if(products.length>0)
{
selectlist += "<select>";
for(var i = 0; i < products.length; i++) {
var currency = json[i];
selectlist += "<option value="+currency.code+"> "+currency.code+" </option>";
}
selectlist += "</select>"
if("body").append(selectlist);
}

json multidimensional array to tree structure in javascript

I have this JSON response:
[
{storeWebsites=[
{website_id=1.0, name=Default Store View},
{website_id=0.0, name=Admin}
]},
{storeGroups=[
{website_id=0.0, name=Default, id=0.0},
{website_id=1.0, name=Main Website Store, id=1.0}
]},
{storeViews=[
{website_id=1.0, name=Default Store View, code=default, id=1.0},
{website_id=0.0, name=Admin, code=admin, id=0.0}
]}
]
I would like to group the "website_id" and append the "storeViews.name".
I'm trying to work with the script below but I'm not able to push the values in var group:
var groups = {};
// .... code to push the values in var groups
$.each(groups, function(key, groups) {
var $group1 = $("<optgroup>").attr("label", " " + groups.storeWebsites);
var $group2 = $("<optgroup>").attr("label", " " + groups.storeGroups);
groups.storeViews.forEach(function(el) {
$group2.append(new Option(el.name, el.code));
});
$('#provider-accounts').append($group1, $group2);
});
}
So my "id=provider-accounts" should be populated like below:
<optgroup label="Default Store View"></optgroup>
<optgroup label="Main Website Store">
<option code="default">Default Store View</option>
</optgroup>
<optgroup label="Admin"></optgroup>
<optgroup label="Default">
<option code="admin">Admin</option>
</optgroup>
Any help?
I think you have the following groups swapped:
<optgroup label="Default">
<optgroup label="Main Website Store">
Anyways, you could destructure your sites, groups, and views and keep track of their indices while looping over one of them.
const main = () => {
const [ { storeWebsites }, { storeGroups }, { storeViews }] = json;
$('#provider-accounts').append(storeWebsites.flatMap((site, index) => {
const
group = storeGroups[index],
view = storeViews[index];
return [
$('<optgroup>', { label: site.name }),
$('<optgroup>', { label: group.name })
.append($('<option>', { code: view.code, text: view.name }))
];
}));
};
const json = [{
"storeWebsites": [{
"website_id": 1.0,
"name": "Default Store View"
}, {
"website_id": 0.0,
"name": "Admin"
}]
}, {
"storeGroups": [{
"website_id": 0.0,
"name": "Default",
"id": 0.0
}, {
"website_id": 1.0,
"name": "Main Website Store",
"id": 1.0
}]
}, {
"storeViews": [{
"website_id": 1.0,
"name": "Default Store View",
"code": "default",
"id": 1.0
}, {
"website_id": 0.0,
"name": "Admin",
"code": "admin",
"id": 0.0
}]
}];
main();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="provider-accounts">
<!--
<optgroup label="Default Store View"></optgroup>
<optgroup label="Default">
<option code="default">Default Store View</option>
</optgroup>
<optgroup label="Admin"></optgroup>
<optgroup label="Main Website Store">
<option code="admin">Admin</option>
</optgroup>
-->
</select>

show only related item in the second select form using javascript

I'm writing a small php page with 2 form:
<div class="input-field col s12">
<select id="select1">
<option value="" disabled selected>Choose your option</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<select id="select2">
<option value="" disabled selected>Choose your option</option>
<option rel="1" value="11">Option 11</option>
<option rel="1" value="12">Option 12</option>
<option rel="2" value="21">Option 21</option>
<option rel="2" value="22">Option 22</option>
<option rel="3" value="31">Option 31</option>
<option rel="3" value="32">Option 32</option>
</select>
</div>
After I select the first select form, I want that only the related values are showed in the second.
My js is:
$(function() {
$("#select1").on('change', function() {
$subcat = $("#select2");
var _rel = $(this).val();
$subcat.find("[rel="+_rel+"]").show();
$subcat.prop("disabled",false);
// re-initialize material-select
$('#select2').material_select();
});
});
I also try with
var selectobject=document.getElementById("select2")
for (var i=0; i<selectobject.length; i++)
{
if (selectobject.options[i].value == 'xxxx' )
{
selectobject.remove(i);
}
}
But I need the name option, not the value.
$(function(){
$('#select1').on('change', function(){
var val = $(this).val();
var sub = $('#select2');
$('option', sub).filter(function(){
if ($(this).attr('rel') === val) {
if ($(this).parent('span').length) {
$(this).unwrap();
}
} else {
if (!$(this).parent('span').length) {
$(this).wrap( "<span>" ).parent().hide();
}
}
});
});
});
I don't see which options at the second form corresponding to the first, however, try populating the second select rather than removing items from it. like:
<select id="select1" onchange="myfunction(this.value)">
<script>
function myfunction(opt){
var $Select2 = $('#select2');
var option1 = [
{
"name": "option description",
"value": "1"
}, {
"name": "option description",
"value": "1"
}]
var option2 = [
{
"name": "option description",
"value": "1"
}, {
"name": "option description",
"value": "1"
}]
if(opt === option1){
$.each(option1, function (i, item) {
$('#mySelect').append($('<option>', {
value: item.value,
text : item.name
}));
});
}
if(opt === option2){
$.each(option2, function (i, item) {
$('#mySelect').append($('<option>', {
value: item.value,
text : item.name
}));
});
}
}
</script>

Combo Select using json

The country and state will be sent as json
{
"data": [
{
"country": "USA",
"states": [
"Alabama",
"Alaska",
"Arizona"
]
},
{
"country": "India",
"states": [
"TN",
"AP",
"Mumbai"
]
}
]
}
There will be two select tags (country and state). How do I populate the states based on the country selected?
I am looking for a solution similar to http://www.datatables.net/examples/api/row_details.html where the row.data() returns the data set of a particular row.
Here's a very simple pure JavaScript way to populate two select boxes via JSON. In this example, State is dependent upon which Country is selected.
Example: http://jsfiddle.net/wasfd592/
HTML:
<select id="country">
<option>Country</option>
</select>
<select id="state">
<option>State</option>
</select>
JSON Object (assigned to variable d):
var d = {
"data": [
{
"country": "USA",
"states": [
"Alabama",
"Alaska",
"Arizona"
]
},
{
"country": "India",
"states": [
"TN",
"AP",
"Mumbai"
]
}
]
}
JavaScript:
// First - populate the Country select box from the JSON
for (var i in d.data) {
var elem = document.createElement("option");
elem.value = d.data[i].country;
elem.innerHTML = d.data[i].country;
document.getElementById("country").appendChild(elem);
}
// Next - add an event handler that will trigger when Country is changed and populate the State box
document.getElementById("country").addEventListener("change", function () {
document.getElementById("state").innerHTML = "";
var country = document.getElementById("country").options[document.getElementById("country").selectedIndex].value;
if (country === "Country") {
var elem = document.createElement("option");
elem.value = "State";
elem.innerHTML = "State";
document.getElementById("state").appendChild(elem);
}
for (var i in d.data) {
if (d.data[i].country === country) {
for (var a = 0; a < d.data[i].states.length; a++) {
var elem = document.createElement("option");
elem.value = d.data[i].states[a];
elem.innerHTML = d.data[i].states[a];
document.getElementById("state").appendChild(elem);
}
}
}
});
Try this out:- http://jsfiddle.net/ox4ykqoL/
HTML:-
<select id="country"></select>
<select id="states"></select>
JS:-
jQuery(function ($) {
var input = {
"data": [{
"country": "USA",
"states": [
"Alabama",
"Alaska",
"Arizona"]
}, {
"country": "India",
"states": [
"TN",
"AP",
"Mumbai"]
}]
};
$.each(input.data, function (index, d) {
$("#country").append("<option value=\"" + d.country + "\">" + d.country + "</option>");
});
$("#country").on("change", function () {
var selectedCountry = $("#country").val();
var t = $.map(input.data, function (obj) {
if (obj.country === selectedCountry) return obj;
});
if (t.length != 0) {
$('#states').empty();
debugger;
$.each(t[0].states, function (index, d) {
$("#states").append("<option value=\"" + d + "\">" + d + "</option>");
});
}
});
$("#country").change();
});

Categories

Resources