Bind SELECT Element with an Array of objects using JavaScript - javascript

I am trying to populate a SELECT dropdown list with an array of objects using JavaScript and then display properties of that object based on the option selection. So far I have been able to populate the dropdown, however I can't seem to get the output correctly, as it only selects the last value in the for loop and hence only outputs the last object, for each selection. I thought this might be a closure issue, but I have gone through a lot closure solutions and none seem to work. How can I get each option selection to display the right object properties?
<html>
<body>
<input type="button" onclick="populateSelect()" value="Click to Populate SELECT" />
<!--The SELECT element.-->
<select id="sel" onchange="show()">
<option value="">-- Select --</option>
</select>
<p id="msg"></p>
</body>
<script>
// THE ARRAY.
var birds = [
{ID: 001, Bird_Name: "Eurasian Collared-Dove"},
{ID: 002, Bird_Name: "Bald Eagle"},
{ID: 003, Bird_Name: "Cooper's Hawk"},
];
function populateSelect() {
var ele = document.getElementById('sel');
for (var i = 0; i < birds.length; i++) {
// POPULATE SELECT ELEMENT WITH JSON.
ele.innerHTML = ele.innerHTML +
'<option>' + birds[i]['Bird_Name'] + '</option>';
}
}
function show() {
// GET THE SELECTED VALUE FROM <select> ELEMENT AND SHOW IT.
var msg = document.getElementById('msg');
for (var i = 0; i < birds.length; i++)
{
msg.innerHTML = birds[i].ID + " " + birds[i].Bird_Name;
}
}
</script>
</html>

You should use a value for the options and pass that value into your event handler function. Then compare selected value to the elements in array as well as set a default if no value selected
var birds = [
{ID: 001, Bird_Name: "Eurasian Collared-Dove"},
{ID: 002, Bird_Name: "Bald Eagle"},
{ID: 003, Bird_Name: "Cooper's Hawk"},
];
function populateSelect() {
var ele = document.getElementById('sel');
birds.forEach(function(b) {
ele.innerHTML += '<option value="' + b.ID + '">' + b['Bird_Name'] + '</option>';
})
}
function show(id) {
// GET THE SELECTED VALUE FROM <select> ELEMENT AND SHOW IT.
var msg = document.getElementById('msg');
if (!id) {
msg.innerHTML = 'None selected';
} else {
for (var i = 0; i < birds.length; i++) {
if (Number(id) === birds[i].ID) {
msg.innerHTML = birds[i].ID + " " + birds[i].Bird_Name;
break;
}
}
}
}
populateSelect()
<select id="sel" onchange="show(this.value)">
<option value="">-- Select --</option>
</select>
<p id="msg"></p>

You should use the value attribute in tag, also as one of the comment mentions you can make use of the events too.
// THE ARRAY.
var birds = [{
ID: 001,
Bird_Name: "Eurasian Collared-Dove"
},
{
ID: 002,
Bird_Name: "Bald Eagle"
},
{
ID: 003,
Bird_Name: "Cooper's Hawk"
},
];
var select = document.getElementById('sel');
function populateSelect() {
for (var i = 0; i < birds.length; i++) {
// POPULATE SELECT ELEMENT WITH JSON.
// add the value attribute in option as the id of bird
select.innerHTML = select.innerHTML +
'<option value=' + birds[i].ID + '>' + birds[i]['Bird_Name'] + '</option>';
}
}
function show() {
// GET THE SELECTED VALUE FROM <select> ELEMENT AND SHOW IT.
var msg = document.getElementById('msg');
// find the bird with the selected id
let selectedBird = birds.find(bird => bird.ID == select.value);
// display the info
msg.innerHTML = selectedBird.ID + " " + selectedBird.Bird_Name;
}
<html>
<body>
<input type="button" onclick="populateSelect()" value="Click to Populate SELECT" />
<!--The SELECT element.-->
<select id="sel" onchange="show()">
<option value="">-- Select --</option>
</select>
<p id="msg"></p>
</body>
</html>

Related

Get the selected value from populating select options

var regionOption = document.querySelector("#municipality");
var districtOption = document.querySelector("#districtName");
var provOption = document.querySelector("#region");
createOption(provOption, Object.keys(regions));
provOption.addEventListener('change', function() {
createOption(regionOption, regions[provOption.value]);
});
regionOption.addEventListener('change', function() {
createOption(districtOption, districts[regionOption.value]);
});
function createOption(dropDown, options) {
dropDown.innerHTML = '';
options.forEach(function(value) {
dropDown.innerHTML += '<option name="' + value + '">' + value + '</option>';
});
};
CSS:
<select id="region" style="width: 125px;"></select>
<select id="municipality" style="width: 125px;"></select>
<select id="districtName" style="width: 125px;"></select>
So, I'm populating options for an empty select and I was wondering how to get the value of the selected option. I basically want to check if (select value = 'A' && another selecte value = 'B') { do something}
Set the value attribute on each <option>:
<option value="' + value + '">
Then, simply check the value property on the <select>.
if (document.getElementById("region").value === 'A') {
// ...
}

How to design UI for multiple selection in a drop down list?

I'm setting up a UI for my application. I would like to have some idea about your guy's experiences.
I need to have multiple selections from different sources.
Input (Sources): Companies, Department. Multiple companies, departments allowed.
Output: People who belong to selected items
For example, I can select company1, company2, and select department1, department2 from a dropdown list.
I select one by one property( Select company1, company2, then go to another dropdown to select department1,2...)
In the end, I have company1,2,3 checked, department 1,2,3 checked.
Then the result will tell me user1...n belong to the selected list above.
The problem is nothing if I have only a few company and department but if coming to be complicated if I have multiple (more than 6 companies and departments). I can't come up with any good UI design for this problem.
I expected the output of (selected(checked company1,2,3... + department1,2,3)) -> result person1,2,3 belong to checked items.
Try the following code:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>Select Company: </p>
<select name="companySelector" multiple>
</select>
<p>Select Department: </p>
<select name="departmentSelector" multiple>
</select>
<p>Persons: </p>
<ul id="persons">
</ul>
<script>
var companySelector = document.querySelector("[name='companySelector']");
var departmentSelector = document.querySelector("[name='departmentSelector']");
var persons = document.getElementById("persons");
var temp, temp2 = 0;
var database = {
company_1: {
c1_department1: ["c1d1person1", "c1d1person2", "c1d1person3", "c1d1person4"],
c1_department2: ["c1d2person1", "c1d2person2", "c1d2person3", "c1d2person4"],
c1_department3: ["c1d3person1", "c1d3person2", "c1d3person3", "c1d3person4"]
},
company_2: {
c2_department1: ["c2d1person1", "c2d1person2", "c2d1person3", "c2d1person4"],
c2_department2: ["c2d2person1", "c2d2person2", "c2d2person3", "c2d2person4"],
c2_department3: ["c2d3person1", "c2d3person2", "c2d3person3", "c2d3person4"]
},
company_3: {
c3_department1: ["c3d1person1", "c3d1person2", "c3d1person3", "c3d1person4"],
c3_department2: ["c3d2person1", "c3d2person2", "c3d2person3", "c3d2person4"],
c3_department3: ["c3d3person1", "c3d3person2", "c3d3person3", "c3d3person4"]
},
company_4: {
c4_department1: ["c4d1person1", "c4d1person2", "c4d1person3", "c4d1person4"],
c4_department2: ["c4d2person1", "c4d2person2", "c4d2person3", "c4d2person4"],
c4_department3: ["c4d3person1", "c4d3person2", "c4d3person3", "c4d3person4"]
},
company_5: {
c5_department1: ["c5d1person1", "c5d1person2", "c5d1person3", "c5d1person4"],
c5_department2: ["c5d2person1", "c5d2person2", "c5d2person3", "c5d2person4"],
c5_department3: ["c5d3person1", "c5d3person2", "c5d3person3", "c5d3person4"]
}
}
for (temp in database) {
companySelector.innerHTML += '<option value="' + temp + '">' + temp.replace(/_/g, " ") + '</option>';
}
companySelector.onchange = function() {
departmentSelector.innerHTML = "";
var selectedCompnies = document.querySelectorAll("[name='companySelector'] option:checked");
for (var i = 0; i < selectedCompnies.length; i++) {
for (temp2 in database[selectedCompnies[i].value]) {
departmentSelector.innerHTML += '<option value="' + temp2 + '" data-company="' + selectedCompnies[i].value + '">' + temp2.replace(/_/g, " ") + '</option>'
}
}
}
departmentSelector.onchange = function() {
persons.innerHTML = "";
var selectedDepartments = document.querySelectorAll("[name='departmentSelector'] option:checked");
for (var i = 0; i < selectedDepartments.length; i++) {
var temp3 = selectedDepartments[i].dataset.company;
var prsonsArray = database[temp3][selectedDepartments[i].value];
for (var x = 0; x < prsonsArray.length; x++) {
persons.innerHTML += "<li>" + prsonsArray[x] + "</li>";
}
}
}
</script>
</body>
</html>
DEMO

JSON accessing array objects using a named index

Suppose I have this HTML
<form action="#" action="get">
<select name="college" id="college" onchange="selection('college', 'course')">
<option value="">Select an Option</option>
<option value="amity">Amity University</option>
<option value="indraprastha">Indraprasth University</option>
</select>
<br>
<select name="course" id="course" onchange="selection('course', 'stream')" >
<option value="">Select an Option</option>
</select>
<br>
<select name="stream" id="stream">
<option value="">Select an Option</option>
</select>
</form>
I have this JSON,
{
"amity":{
"course":[
{
"name":"B.Tech",
"value":"btech",
"stream":[
{
"name":"Computer Science",
"value":"cse"
},
{
"name":"Information Technology",
"value":"cse"
},
{
"name":"Aerospace Engg.",
"value":"cse"
}
]
},
{
"name":"M.Tech",
"value":"mtech",
"stream":[
{
"name":"Networking",
"value":"net"
},
{
"name":"telecommunications",
"value":"tc"
}
]
}
]
}
}
The Javascript is,
function selection(s1, s2) {
var first = document.getElementById(s1),
second = document.getElementById(s2);
var college = $('#college').val(),
cr = $('#course').val(),
st = $('#stream').val(),
se = $('#sem').val();
$.getJSON("json/select.json", function(data) {
switch(s1) {
case 'college':
$.each(data[college].course, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
}); break;
case 'course':
$.each(data[college].course[].stream, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
}); break;
}
});
}
I am making a dynamic drop-down menu where the next drop down values are fetched from JSON object file, using the reference of previous values. As suggested from my this question (link), I am able to get the value of course (second drop-down) using the course array in the object.
Now, since the values in the second select menu(course) are filled dynamically, I can't figure out how to take the corresponding course array element to fill the next select menu options for stream array.
Since the course property in JSON is an array, I don't know which index element element is chosen from second menu (See the switch case for 'course', the data[college].course[] index is empty). The hardcoded [0] works, but that's not dynamic then.
How to access the stream array using the values of course grabbed from second menu.
I hope I am clear. Thanks in advance!
Just iterate through array of courses to get the stream dynamically:
for (var i = 0; i < data[college].course.length; i++) {
currentStream = data[college].course[i].stream;
}
I.e. using your code:
for (var i = 0; i < data[college].course.length; i++) {
$.each(data[college].course[i].stream, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
});
}
Finding the current stream for your selected course:
// assuming cr = "btech"
for (var i = 0; i < data[college].course.length; i++) {
if (data[college].course[i].value == cr) {
currentStream = data[college].course[i].stream;
break;
}
}
$.each(currentStream, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
});
function selection(s1, s2) {
var first = document.getElementById(s1),
second = document.getElementById(s2);
var college = $('#college').val(),
cr = $('#course').val(),
st = $('#stream').val(),
se = $('#sem').val();
$.getJSON("json/select.json", function(data) {
switch(s1) {
case 'college':
$.each(data[college].course, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
}); break;
case 'course':
var course = data[college].course;
for(var i = 0;i<course.length;i++){
if(course[i].name === cr){ //cr is selected option
$.each(course[i].stream, function(key, value) {
second.innerHTML += '<option value="'+ value.value +'">'+ value.name +'</option>';
}
}
}); break;
}
});
}

Adding HTML form using JavaScript to get a total in text box

So for the final piece of my code, I need to add all the form values together and show a running total in a textbox underneath the 'table'. Is there a way using JavaScript that this can be done? I have my drop down boxes with values in them.
This is a snippet of my code:
function eraseText() {
var out = document.querySelectorAll(".out");
for (var i=0;i<out.length;i++) {
out[i].value="";
}
}
var sections = {
p1 : {sname: "Dynamic Table ", mscore: 20},
p2 : {sname: "IntelliJ Usage ", mscore: 10},
p3 : {sname: "Calender Control", mscore: 30},
p4 : {sname: "Active Form ", mscore: 20},
p5 : {sname: "Object Database ", mscore: 20}
};
document.write("<pre>");
document.write(Object.keys(sections).reduce(function(s, p, i) {
var o = sections[p];
return s + (i>0?'<br><br><br><br>':'')
+ o.sname + ' '
+ o.mscore + ' '
+ '<textarea class="out" id="output" rows="4" cols="25"></textarea>'
+ ' '
+ '<select>'
+ '<option value="1">1</option>'
+ '<option value="2">2</option>'
+ '<option value="3">3</option>'
+ '</select>' }, '')
);
document.write("</pre>");
Something like this?
var selects = [].slice.call(document.querySelectorAll('select')); // [].slice.call turns NodeList into an array
var total = selects.reduce(function (previousValue, select) {
previousValue += select.options[select.selectedIndex].value || 0;
}, 0);
// ... then query for textbox, set the value of it to 'total'
You'd want to bind to the onchange event of each select, and recalculate the sum each time.
var output = document.getElementById('output'),
selects = document.querySelectorAll('select');
//helper method
function doToAll(elems, fn) {
var len = elems.length;
while (--len > -1) {
fn(elems[len]);
}
}
//sum values
function sumSelects() {
var sum = 0;
doToAll(selects, function(t) {
sum += parseInt(t.value);
});
return sum;
}
//bind to onchange event
doToAll(selects, function(t) {
t.addEventListener('change', function() {
output.textContent = sumSelects();
});
});
//run once on load
window.addEventListener('load', function() {
output.textContent = sumSelects();
});
<select>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
</select>
<select>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
</select>
<select>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
</select>
<p>The current total is
<span id="output"></span>
</p>

Jquery append html weird behavior

i have the following ajax:
$.ajax({
type: 'POST',
url: myBaseUrl + 'Products/ajax_get_subcategories',
dataType: 'json',
data: {
id: id
},
success: function (data) {
var length = data.length;
var div_subcategory = $('#subcategory');
div_subcategory.html('');
div_subcategory.append(
"<select id='subcategory' name='data[Product][subcategory_id]'>"
);
for (var i = 0; i < length; i++) {
var id = data[i]['Subcategory']['id'];
var name = data[i]['Subcategory']['name'];
$('#subcategory').append(
"<option value=''+id>" + name + "</option>"
);
}
div_subcategory.append("</select>");
}
});
Now as you can see it appends a select into a div block.
But! there is a catch here is the output of the HTML after the ajax has been called:
div id="subcategory" class="subcategory">
<select id="subcategory" name="data[Product][subcategory_id]"></select>
<option +id="" value="">Telte</option>
<option +id="" value="">Toilet</option>
<option +id="" value="">Service</option>
<option +id="" value="">Borde</option>
<option +id="" value="">Stole</option>
<option +id="" value="">Lyd og lys</option>
</div>
As you can see it closes the select tag before adding the options.
Can anyone tell me why this is happening?
When you write:
div_subcategory.append("<select id='subcategory' name='data[Product][subcategory_id]'>");
jQuery will insert
<select id='subcategory' name='data[Product][subcategory_id]'></select>
And becasue div_subcategory will have the same id as the select you will be matching the div instead.
Instead I would write this by creating the html in a string and injecting it all at once.
var html += "<select id='subcategorysel' name='data[Product][subcategory_id]'>";
for (var i = 0; i < length; i++) {
var id = data[i]['Subcategory']['id'];
var name = data[i]['Subcategory']['name'];
html += "<option value=''+id>" + name + "</option>";
}
html += "</select>";
div_subcategory.append(html);
This snippet updates your code to use different ids and appends the html all in one go which should be quicker.
Try
change your success code
success: function (data) {
var length = data.length;
var div_subcategory = $('#subcategory');
div_subcategory.html('');
var select_append = "<select id='subcategory' name='data[Product][subcategory_id]'>";
for (var i = 0; i < length; i++) {
var id = data[i]['Subcategory']['id'];
var name = data[i]['Subcategory']['name'];
select_append += "<option value=''" + id + ">" + name + "</option>";
}
select_append += "</select>"
div_subcategory.append(select_append);
}
create a variable select_append and concatenate all your code in that and append that variable in the end.
Try
$(div_subcategory).find('select').append(...)
when you write this syntex
div_subcategory.append(
"<select id='subcategory' name='data[Product][subcategory_id]'>"
);
DOM automatically detects an HTML element like this
<select id='subcategory' name='xxx'></select>
and then you are appending other option elements after this
so solution is first make a string of an HTML and then append like
var html = "<select id='subcategory' name='data[Product][subcategory_id]'>";
for (var i = 0; i < length; i++) {
var id = data[i]['Subcategory']['id'];
var name = data[i]['Subcategory']['name'];
html += "<option value='' + id>" + name + "</option>";
}
div_subcategory.append(html);

Categories

Resources