Can't populate multiple dropdowns with JSON data, no errors - javascript

I have a JSON file with the information of watches. I want to build a simple form that allows a user to select a brand of watch, then the second dropdown would be populated with the values within "Model" and the final dropdown would be populated with the values within "Movement".
I've built what I assume to be right only it isn't working and I'm getting no errors?
HTML
<form name="myform" id="myForm">
<select name="optone" id="brands" size="1">
<option value="" selected="selected">Select a brand</option>
</select>
<br>
<br>
<select name="opttwo" id="model" size="1">
<option value="" selected="selected">Please select model</option>
</select>
<br>
<br>
<select name="optthree" id="movement" size="1">
<option value="" selected="selected">Please select a movement</option>
</select>
</form>
HTML
var watches = {
"Rolex": {
"Model": [
"Submariner",
"Yachtmaster",
"Oyster",
"Datejust"
],
"Movement": [
{
"label": "OysterDate",
"Id": "6694"
},
{
"label": "Hulk",
"Id": "3920"
},
{
"label": "DeepSea",
"Id": "2342"
}
]
},
"Omega": {
"Model": [
"Seamaster",
"Speedmaster",
"MoonWatch"
],
"Movement": [
]
}
}
window.onload = function () {
var brands = document.getElementById("brands"),
model = document.getElementById("model"),
movement = document.getElementById("movement");
for (var brand in watches) {
brands.options[brands.options.length] = new Option(brands, brands);
}
brands.onchange = function () {
model.length = 1; // remove all options bar first
testCase.length = 1; // remove all options bar first
if (this.selectedIndex < 1) return; // done
for (var model in watches[this.value]) {
model.options[model.options.length] = new Option(model, model);
}
}
brands.onchange(); // reset in case page is reloaded
model.onchange = function () {
movement.length = 1; // remove all options bar first
if (this.selectedIndex < 1) return; // done
var movement = watches[brand.value][this.value];
alert(movement);
for (var i = 0; i < movement.length; i++) {
movement.options[movement.options.length] = new Option(movement, movement);
}
}
}
watches();
https://jsfiddle.net/z3xcyprt/3/

Ok, there were a lot of issues here.
Mainly over writing your variable names, but also incorrect navigation of array values, using the for( x in obj) when you should use forEach(func())
Also note that you JSON does not have a relationship between Model and Movement I noted this in the script, but you will likely want to look at that.
var watches = {
"Rolex": {
"Model": [
"Submariner",
"Yachtmaster",
"Oyster",
"Datejust"
],
"Movement": [
{
"label": "OysterDate",
"Id": "6694"
},
{
"label": "Hulk",
"Id": "3920"
},
{
"label": "DeepSea",
"Id": "2342"
}
]
},
"Omega": {
"Model": [
"Seamaster",
"Speedmaster",
"MoonWatch"
],
"Movement": [
]
}
}
const createOption = (value, text) => {
let opt = document.createElement('option');
opt.value = value;
opt.text = text;
return opt;
};
window.onload = function () {
var brands = document.getElementById("brands"),
model = document.getElementById("model"),
movement = document.getElementById("movement");
for (var brand in watches) {
brands.options.add(createOption(brand, brand));
}
brands.onchange = function () {
model.length = 1; // remove all options bar first
if (brands.selectedIndex < 1) return; // done
// This is an array of string.
watches[brands.value].Model.forEach(m => {
model.add( createOption(m, m));
});
}
// There is NO link in the JSON between model and movement ?
model.onchange = function () {
movement.length = 1; // remove all options bar first
if (this.selectedIndex < 1) return; // done
watches[brands.value].Movement.forEach(m => {
movement.options.add(createOption(m.Id, m.label));
});
}
}
// This does nothing.
//watches();
<form name="myform" id="myForm">
<select name="optone" id="brands">
<option value="" selected="selected">Select a brand</option>
</select>
<br>
<br>
<select name="opttwo" id="model">
<option value="" selected="selected">Please select model</option>
</select>
<br>
<br>
<select name="optthree" id="movement">
<option value="" selected="selected">Please select a movement</option>
</select>
</form>

Try with this.
On window.onload function you are declaring the brands, model but you are overriding it in the loops.
Also read about the differences between for ... of and for ... in
window.onload = function () {
var brands = document.getElementById("brands"),
model = document.getElementById("model"),
movement = document.getElementById("movement");
for (var brand in watches) {
brands.options[brands.options.length] = new Option(brand);
}
brands.onchange = function () {
if (this.selectedIndex < 1) return; // done
for (var modelValue of watches[this.value].Model) {
model.options[model.options.length] = new Option(modelValue);
}
}
brands.onchange(); // reset in case page is reloaded
model.onchange = function () {
if (this.selectedIndex < 1) return; // done
var movementValue = watches[brands.value].Movement;
for (var i = 0; i < movementValue.length; i++) {
movement.options[movement.options.length] = new Option( movementValue[i].label, movementValue[i].Id);
}
}
}
watches();

Related

Cascading Dropdown with multiselect options

I built my cascading dropdown with three options , i need to have the second one with multiple choice but if i put multiple on , it's so ugly so can i some one help me to have one nice , i do it on wordpress but i generate all with this script
var subjectObject = {
"Front-end": {
"HTML": ["Links", "Images", "Tables", "Lists"],
"CSS": ["Borders", "Margins", "Backgrounds", "Float"],
"JavaScript": ["Variables", "Operators", "Functions", "Conditions"]
},
"Back-end": {
"PHP": ["Variables", "Strings", "Arrays"],
"SQL": ["SELECT", "UPDATE", "DELETE"]
}
}
window.onload = function() {
var subjectSel = document.getElementById("subject");
var topicSel = document.getElementById("topic");
var chapterSel = document.getElementById("chapter");
for (var x in subjectObject) {
subjectSel.options[subjectSel.options.length] = new Option(x, x);
}
subjectSel.onchange = function() {
    //empty Chapters- and Topics- dropdowns
    chapterSel.length = 1;
    topicSel.length = 1;
//display correct values
for (var y in subjectObject[this.value]) {
topicSel.options[topicSel.options.length] = new Option(y, y);
}
}
topicSel.onchange = function() {
    //empty Chapters dropdown
    chapterSel.length = 1;
//display correct values
var z = subjectObject[subjectSel.value][this.value];
for (var i = 0; i < z.length; i++) {
chapterSel.options[chapterSel.options.length] = new Option(z[i], z[i]);
}
}
}
Subjects: <select name="subject" id="subject">
<option value="" selected="selected">Select subject</option>
</select>
<br><br>
Topics: <select name="topic" id="topic" multiple>
<option value="" selected="selected" >Please select subject first</option>
</select>
<br><br>
Chapters: <select name="chapter" id="chapter">
<option value="" selected="selected">Please select topic first</option>
</select>
I want to have this solution but i can't make it maybe because the list is generated by JS .
enter image description here

Update output displayed json data when changing select value dropdown

I basically want to dynamically update the displayed output json fields based on what value I select in a dropdown, without reloading the page. In this case, display the city based on the selected AveragePrice dropdown. By the way, it's plain javascript (Vanilla)
JSON:
[
{
"country":"UK",
"cities":[
{
"city":"Manchester",
"averagePrice":100
},
{
"city":"London",
"averagePrice":300
},
]
},
{
"country":"France",
"cities":[
{
"city":"Toulouse",
"averagePrice":150
},
{
"city":"Nice",
"averagePrice":200
},
]
},
]
HTML:
<div id="city"></div>
<select id="averagePriceDropdown">
<option value="100">100</option>
<option value="150">150</option>
<option value="175">175</option>
<option value="200">200</option>
<option value="300">300</option>
</select>
Javascript:
var valueDropdown = document.getElementById("averagePriceDropdown");
var valueData = valueDropdown.options[valueDropdown.selectedIndex].value;
var getAverage = async function () {
fetch("../data/data.json").then(
res => {
res.json().then(
data => {
for (var x in data) {
if (data[x].cities[x].averagePrice == valueData) {
return document.getElementById("city").innerHTML += data[x].cities[x].city;
} else {
return document.getElementById("city").innerHTML += "Could not find city.";
}
}
}
)
}
)
};
As you can see, I'm defining variable names for different ID fields. In the IF condition, I am updating the city text content (innerHTML) matching the AveragePrice. It works if I change the default dropdown value in the HTML and reload the page, it renders the correct city. But changing the dropdown on the page, it doesn't update the city. I tried adding an onchange eventlistener to the dropdown but with no success.
The issue is that you are not referencing the array elements correctly. Here is how you want to cycle through the data and make the comparison:
function choose(){
var valueDropdown = document.getElementById("averagePriceDropdown");
var valueData = valueDropdown.options[valueDropdown.selectedIndex].value;
var i, j, match;
match = false;
for (i = 0; i< data.length; i++) {
for (j = 0; j < data[i].cities.length; j++){
if (data[i].cities[j].averagePrice == valueData){
match = true;
console.log("Matching cities: " + data[i].cities[j].city);
document.getElementById("city").innerHTML = data[i].cities[j].city
}
}
}
if (match == false) {
console.log("No matching cities for average price = " + valueData);
document.getElementById("city").innerHTML = "No matching cities.";
}
}
data =
[
{
"country":"UK",
"cities":[
{
"city":"Manchester",
"averagePrice":100
},
{
"city":"London",
"averagePrice":300
},
]
},
{
"country":"France",
"cities":[
{
"city":"Toulouse",
"averagePrice":150
},
{
"city":"Nice",
"averagePrice":200
},
]
},
]
<div id="city"></div>
<select id="averagePriceDropdown" onchange="choose()">
<option value="-">-</option>
<option value="100">100</option>
<option value="150">150</option>
<option value="175">175</option>
<option value="200">200</option>
<option value="300">300</option>
</select>

Cascading Dropdowns using Javascript

I am trying to implement a cascading drop down using this. I'm not really familiar with Javascript but I think I'm on the right track. It should display the array values [0, 1, 2, 3] as opposed to the values ["Name", "Definition", "Owner"]
var typeObject = {
StoredProcedures: ["Name", "Definition", "Owner"],
Tables: ["Name", "Definition", "Owner", "Schema"],
Views: ["Name", "Definition", "Owner"]
}
window.onload = function() {
var typeSel = document.getElementById("typeSel"),
fieldSel = document.getElementById("fieldSel")
for (var type in typeObject) {
typeSel.options[typeSel.options.length] = new Option(type, type);
}
typeSel.onchange = function() {
fieldSel.length = 1; // remove all options bar first
if (this.selectedIndex < 1) return; // done
for (var field in typeObject[this.value]) {
fieldSel.options[fieldSel.options.length] = new Option(field, field);
}
}
typeSel.onchange();
I made a modification to your script
var typeObject = {
StoredProcedures: ["Name", "Definition", "Owner"],
Tables: ["Name", "Definition", "Owner", "Schema"],
Views: ["Name", "Definition", "Owner"]
}
window.onload = function () {
var typeSel = document.getElementById("typeSel"),
fieldSel = document.getElementById("fieldSel")
for (var type in typeObject) {
typeSel.options[typeSel.options.length] = new Option(type, type);
}
typeSel.onchange = function () {
fieldSel.length = 1; // remove all options bar first
if (this.selectedIndex < 1) return; // done
var ft = typeObject[this.value];
for (var field in typeObject[this.value]) {
fieldSel.options[fieldSel.options.length] = new Option(ft[field], field);
}
}
typeSel.onchange();
}
<select name="optone" id="typeSel" size="1">
<option value="" selected="selected">Select type</option>
</select>
<br/>
<br/>
<select name="opttwo" id="fieldSel" size="1">
<option value="" selected="selected">Select field</option>
</select>

how to obtain values from dynamic dropdown javascript (object)

I've created dynamic dropdown list and I want to obtain values from selected option. Dynamic dropdown works fine but I have struggle with taking values from selected option.
For example I want to take value of avgDamage from selected object tpPrototype.
Need some help here
HTML:
<form name="myform" id="myForm">
<p>tank 1</p>
<div class="select">
<select classname="optone" id="tankSel" size="1">
<option value="" selected="selected">Tank Nation</option>
</select>
</div>
<div class="select">
<select name="opttwo" id="typeSel" size="1">
<option value="" selected="selected">Tank Type</option>
</select>
</div>
<div class="select">
<select name="optthree" id="nameSel" size="1">
<option value="" selected="selected">Tank Name</option>
</select>
</div>
</form>
JavaScript:
const tpPrototype = {
name: "50TP prototyp",
avgDamage: 440,
healthPool: 1500,
reloadTime: 13.62,
},
tpMarkowskiego = {
name: "53TP prototyp",
avgDamage: 420,
healthPool: 1450,
reloadTime: 12.18,
},
proggettoM35 = {
name: "Progetto M35 mod.46",
avgDamage: 240,
healthPool: 1400,
reloadTime: 1,
},
window.onload = function () {
let tankSel = document.getElementById("tankSel");
typeSel = document.getElementById("typeSel");
nameSel = document.getElementById("nameSel");
for (let tank in tankObject) {
tankSel.options[tankSel.options.length] = new Option(tank, tank);
}
tankSel.onchange = function () {
typeSel.length = 1;
nameSel.length = 1;
if (this.selectedIndex < 1) return;
for (let type in tankObject[this.value]) {
typeSel.options[typeSel.options.length] = new Option(type, type);
}
};
tankSel.onchange();
typeSel.onchange = function () {
nameSel.length = 1;
if (this.selectedIndex < 1) return;
let names = tankObject[tankSel.value][this.value];
for (let i = 0; i < names.length; i++) {
nameSel.options[nameSel.options.length] = new Option(names[i], names[i]);
}
};
This looks like a duplicate of question 1085801
Basically, once you have the selection object, you access the "value" attribute through:
var selectedValue = selectionObject.options[index].value;
or you can access the actual text, such as "Tank Type" in your initial HTML as:
var selectedText = selectionObject.options[index].text;
Once you have this, you should just be able to use that value/text to access your "tankObject" property:
var selectedAvgDamage = tpPrototype[selectedText];

disabling options in a dropdown based on another dropdown

I am trying to disable/remove options in a dropdown, based on the selection of other dropdown options.
But the dropdown/selector we have to choose from, has a sub-dropdown list and both main and sub dropdowns are
sharing the same classes and ids but since both are wrapped in different divs with different ids, I have been
trying to access the second selector but couldn't .
Below is the js code that I used for this;
<script type="text/javascript">
document.getElementById("lvl1").querySelector("select").onchange = function()
{
if(this.value=="8"){
var bikeSizes = document.getElementById("pa_size[]");
for ( var i = 1; i <8; i++) {
bikeSizes.options[i].removeAttribute("disabled", "disabled");
}
for ( var i = 8; i < 12; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
} else {
var bikeSizes = document.getElementById("pa_size[]");
for ( var i = 1; i < 8; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
for ( var i = 8; i < 12; i++) {
bikeSizes.options[i].removeAttribute("disabled", "disabled");
}
}
return false;
};
</script>
The html code of the selector/dropdowns are;
— Select —
Camping
Road Sports
Snow Sports
Water Sports
<div id="lvl1" level="1" style="">
<select data-required="yes" data-type="select" name="product_cat" id="product_cat" class="cat-ajax product_cat wpuf_product_cat_">
<option value="-1">— Select —</option>
<option class="level-0" value="8">Bikes</option>
</select>
<span data-taxonomy="{"required":"yes","name":"product_cat","exclude_type":"child_of","exclude":"camping,road-sports,water-sports","orderby":"name","order":"ASC"}"></span>
</div>
I fixed the quote then put it in an onload function. Also, there is no second argument on a removeAttribute. This worked for me.
<script>
window.onload = function () {
document.getElementById("product_cat").onchange = function () {
if (this.value == "8") {
var bikeSizes = document.getElementById("pa_size[]");
for (var i = 1; i < 8; i++) {
bikeSizes.options[i].removeAttribute("disabled");
}
for (var i = 8; i < 12; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
} else {
var bikeSizes = document.getElementById("pa_size[]");
for (var i = 1; i < 8; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
for (var i = 8; i < 12; i++) {
bikeSizes.options[i].removeAttribute("disabled");
}
}
return false;
};
}
</script>
<!-- my test html -->
<div id="lvl1" level="1" style="">
<select data-required="yes" data-type="select" name="product_cat" id="product_cat" class="cat-ajax product_cat wpuf_product_cat_">
<option value="-1">— Select —</option>
<option class="level-0" value="8">Bikes</option>
</select>
<span data-taxonomy="{"required":"yes","name":"product_cat","exclude_type":"child_of","exclude":"camping,road-sports,water-sports","orderby":"name","order":"ASC"}"></span>
<select id="pa_size[]">
<option value="-1">--Select--</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
</select>
</div>
Based on what I saw on your website, here is an alternative solution:
<script>
var group1 = [ { value:"33", text:"Small Unisex"},
{ value:"34", text:"Large Unisex"},
{ value:"35", text:"XL Unisex"},
{ value:"36", text:"Small Womens"},
{ value:"37", text:"Medium Womens"},
{ value:"38", text:"Large Womens"},
{ value:"39", text:"XL Womens"}];
var group2 = [{value:"40", text:"Medium"},
{value:"41", text:"Small"},
{ value:"43", text:"XL"},
{ value:"42", text:"Large"}];
window.onload = function() {
document.getElementById("product_cat").onchange = function () {
var bikeSizes = document.getElementById("pa_size[]");
bikeSizes.innerHTML = "";
bikeSizes.appendChild(new Option("--Select--", "-1"));
bikeSizes.disabled = false;
if (this.value == "-1") {
bikeSizes.disabled = true;
}
else if (this.value == "8") {
for (var i = 0; i < group1.length; ++i){
var opt = new Option(group1[i].text, group1[i].value);
bikeSizes.appendChild(opt);
}
} else {
for (var i = 0; i < group2.length; ++i) {
var opt = new Option(group2[i].text, group2[i].value);
bikeSizes.appendChild(opt);
}
}
return false;
};
}
</script>
so is this closer to what you need? This is 3 select boxes where you can only see the second one after the first one has a valid selection. Then you can only see the third one when the second one has a valid choice.
The options available is dependent on its master select box.
you can see it work here http://jsbin.com/nijahoh/edit?html,js,output
<script>
var fakeData = {
group1: [{ value: "group3", text: "3" }, { value: "group4", text: "4" }],
group2: [{ value: "group5", text: "5" }, { value: "group6", text: "6" }],
group3: [{ value: "group7", text: "7" }, { value: "group8", text: "8" }],
group4: [{ value: "group9", text: "9" }, { value: "group10", text: "10" }]
};
$(document).ready(function(){
// first select box change handler
$("#product_cat").on("change", function () {
var val = this.value;
$("#d").val("-1");
setUpSel($("#d"), val);
$("#d").trigger("change");
$("#d").css("display", val=="-1"?"none":"");
});
$("#d").on("change", function () {
var val = this.value;
$("#c").val("-1");
setUpSel($("#c"), val);
$("#c").trigger("change");
$("#c").css("display", val == "-1" ? "none" : "");
});
});
function setUpSel($sel, group) {
$sel.html("<option value='-1'>--Select--</option>");
var selData = fakeData[group];
$.each(selData, function (i, opt) {
$sel.append(new Option(opt.text, opt.value));
});
}
</script>

Categories

Resources