Display specific data based on a combo box selection - javascript

I have 2 combo boxes. I want to display specific data in combo box 2 based on combobox 1 selection.
But I want to make it an ontime selection ... so when I press on the option I want from combobox 1 , combobox 2 is filled with data matching this selection.
I tried to put an on click function on combobox 1 options, but it didn't work when I click on them ...
So is there some method to do so ?

Assign the change event handler on the first dropdown, and then, based on the selected value, fetch the values that ought to be put in the second dropdown. Here's a typical manufacturer -> model example:
Markup:
​<select id="manufacturers">
<option></option>
<option value="Audi">Audi</option>
<option value="Toyota">Toyota</option>
</select>
<select id="cars">
</select>
JavaScript:
​​var cars = {
Audi: [ 'A2', 'A3', 'A4' ],
Toyota: [ 'Auris', 'Avalon', 'Yaris' ]
}​​​​;
$("#manufacturers").change(function () {
var $this = $(this);
var selectedValue = $this.val();
if (selectedValue) {
var $cars = $("#cars").empty();
var newCars = cars[selectedValue];
$.each(newCars, function () {
console.log(this);
$("<option>" + this + "</option>").appendTo($cars);
});
}
});
​
DEMO.

You should use the change (not click) event on the select tag itself (not on the option tag).
Example:
$('#combo1').change(function() {
// Load new content for #combo2 here
});

$('select.option1').change(function() {
// fill option2 with data from somewhere
});

Chained is simple jQuery plugin for chained selects
http://www.appelsiini.net/projects/chained
I've used this Plugin in some Projects and it works stable and as expected. Feel free to try it…

Related

Replacing options on <select> dynamically from JavaScript array

In a bespoke shopping cart, I pull from my database a list of options that a particular product has. The number of these options can vary by product.
I then turn that list of options into a JavaScript array.
An example with 3 options:
{"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}}
Using the above, I would now like to generate an HTML select field, listing all the "first" options:
<select>
<option value="Small">Small</option>
<option value="Large">Large</option>
<option value="X Large">X Large</option>
</select>
Once the user has selected the first option, I then need another <select> box to then load with options that are available for their selection. So, if they selected "Small" from above, the new select box would be:
<select>
<option value="Super">Super</option>
<option value="Maxi">Maxi</option>
</select>
Finally, when they select from this list, a 3rd select box loads in the final options, along with the part numbers as values:
<select>
<option value="parta">Pack</option>
<option value="parte">Case</option>
</select>
The number of options can vary, from zero to 4. But, each time when options are available, I need to pull the part number based on the users selection. The part number doesn't necessarily need to be the value of the last select, it can be pushed to a new hidden variable.
I can achieve this using ajax, by making an ajax call every time a selection is chosen, but can it be done via JavaScript / jQuery, without having to make ajax calls, given that the array is on the page and available to use?
When you dynamically create the select element, also determine which "node" in your tree structure goes with that element, and use it to:
add a default "Please select..." option to the select element
populate the select element further with the real options
determine the deeper node when an option is selected (also when the initial selection is made when the element is created), and use it to create the next select element with the same function
This cascade stops when the deeper node does not exist (when "Please select..." is selected) or it happens to be a string and not an object.
Here is some code for inspiration:
let optionTree = {"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}};
let container = document.querySelector("#container");
addSelector(optionTree);
function addSelector(node) {
let select = document.createElement("select");
// Start with the default option:
let option = document.createElement("option");
option.text = "Please select...";
select.add(option);
for (let key in node) { // Populate the select element
let option = document.createElement("option");
option.value = key;
option.text = key;
select.add(option);
}
container.appendChild(select); // Add it to the page
function change() {
// Remove select elements that come after the selection
while (select.nextElementSibling) {
select.nextElementSibling.remove();
}
let key = select.value;
if (node[key] && typeof node[key] !== "string") {
addSelector(node[key]); // Create the next select element(s)
}
}
// Call the above function whenever a selection is made
select.addEventListener("change", change);
change(); // ... and also call it now
}
<div id="container"></div>
Assuming you already have the three select elements in the DOM, you can populate the first select, and add a change event listener to both the first and second to achieve this. Try this
let $s1 = document.querySelector('#select-1');
let $s2 = document.querySelector('#select-2');
let $s3 = document.querySelector('#select-3');
let object = {"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}};
// add options to first select
$s1.innerHTML = '<option></option>'; // empty select
Object.keys(object).forEach(val => $s1.append(new Option(val, val))); // append children
$s1.dispatchEvent(new Event('change')); // trigger change event
// listen to change event on first select/get options for second select
$s1.addEventListener('change', function(e){
$s2.innerHTML = '<option></option>'; // empty select
// append children
Object.keys(object[e.target.value] ?? []).forEach(val => {
$s2.appendChild(new Option(val, val));
});
// trigger change event
$s2.dispatchEvent(new Event('change'));
});
// listen to change event on second select/get options for third select
$s2.addEventListener('change', function(e){
$s3.innerHTML = '<option></option>'; // empty select
// append children
Object.entries(object[$s1.value]?.[e.target.value] ?? []).forEach(([key, val]) => {
$s3.appendChild(new Option(key, val));
});
});
select {min-width:80px}
<select id="select-1"></select>
<select id="select-2"></select>
<select id="select-3"></select>

how to refresh select box without reloading the whole form in js?

I am using a form in a modal where i add new fields to the select box and would like to refresh the select box such that the new options are added to it. And this without reloading the entire page . Can someone please tell me if this is possible or not and if it is how do i go about it.
There are multiple ways of doing this:
First if you are using jQuery this is simple like:
$("#dropdownlist").empty();
Another way can be:
for(i = dropdownlist.options.length - 1 ; i >= 0 ; i--)
{
dropdownlist.remove(i);
}
Another simplest way can be:
document.getElementById("dropdownlist").innerHTML = "";
Now if you want to repopulate it. You can append the options with jQuery. If you have single value you can achieve it like:
$('#dropdownlist').append($('<option>', {
value: 1,
text: 'New option'
}));
And if it's a collection. you need to loop over it like the following snippet:
$.each(newOptions, function (i, val) {
$('#dropdownlist').append($('<option>', {
value: val.value,
text : val.text
}));
});
Check this,
$(document).ready(function(){
$("#test").append($('<option>', {value: 2,text: 'Two'}));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="test">
<option value="1">One</option>
</select>
Give it a try, it should work.

jQuery change element on select - global script for multiple select inputs

I am creating a form builder script. I have a select input where the user can select the form element they want to use, depending on their selection ("select", "checkbox" or "radio") another form field is displayed allowing users to input their options.
Users can create as many instances of form elements as they want, so each select input has a dynamically created id that corresponds to the id of the hidden form field. I then use jQuery to determine whether the "options" field should be hidden or not (triggered on change of the form elements select input).
Currently, for every instance, I have the following code addedabove the select input:
<script>
jQuery(document).ready(function($) {
var arr = ['select', 'checkbox', 'radio'];
var thisForm = 'select.input-type-118';
function showHideSelect() {
var val = $(thisForm + ' option:selected').val();
var selectOptions = $('#select-options-118')
if (arr.indexOf(val) >= 0) {
selectOptions.show();
} else {
selectOptions.hide();
}
}
showHideSelect();
$(thisForm).change(function() {
showHideSelect();
});
});
</script>
Where var thisForm and var selectOptions are added dynamically and refer to the select option below this script.
I'm wondering if there is a better way to do this rather than repeat several instances of this, at the moment, a users page cold look like this:
<script>
...
</script>
<select>
...
</select>
<textarea>
This is hidden depending on the select option
</textarea>
<script>
...
</script>
<select>
...
</select>
<textarea>
This is hidden depending on the select option
</textarea>
<script>
...
</script>
<select>
...
</select>
<textarea>
This is hidden depending on the select option
</textarea>
...etc...etc
My concern is that I don't think it's best practice to have so many instances of the same script, but I'm unsure how to write a global script that will allow me to show/hide the textarea on an individual basis.
I have shown a more accurate depiction of my workings on this jsfiddle here:
https://jsfiddle.net/46stb05y/4/
You can use Event Delegation Concepts. https://learn.jquery.com/events/event-delegation/
With this you can change your code to
$(document).on('change','select',function() { //common to all your select items
showHideSelect($(this)); // passing the select element which trigerred the change event
});
This will work even on the select items that are added dynamically
You must change your function to receive the element as the parameter.
function showHideSelect($selectElement) {
var val = $selectElement.val();
var selectOptionsId = $selectElement.attr('class').replace('input-type','select-options');
var selectOptions = $("#"+selectOptionsId);
if (arr.indexOf(val) >= 0) {
selectOptions.show();
} else {
selectOptions.hide();
}
}
Here is the Working JsFiddle

Alert when user select the same <option> in dynamically created <selects>

I have a PHP page that creates multiple selects depending on how many the page before it gives it and creates the same number of options that there are selected (it's to choose the priority).
<select name="select1" id="idSelect" onchange="javascript:SelectOnChange();">
<option value="Select one">Select one</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
What I want to do is, whenever the user chooses an option that was already selected in another selection, to show an alert in order to let them know that their choice has already been taken and deny the change.
I want to compare the currently selected option to every previously selected option every time the user selects something from every select.
Basically your looking for a change event to loop through each select and notify duplicates.
$("select").change(function() {
var currentSelection = this.value;
$("select").each(function() {
if (this.value == currentSelection) {
alert("you've already chosen this!");
}
});
});
Something like this should work
Listen for change events
Get the element's seletedIndex
Grab all of the selects with getElementsByTagName()
Loop through and get the selected index
Compare to see if used
This could maybe work :
var $selects = $('select');
// WHen a select is changed.
$selects.onchange(function() {
// Storing it's selected value, assuming there is only one per select.
var value = $(this).selected().first().attr('value');
var $changedSelect = $(this);
// For each select...
$selects.each(function() {
var $otherSelect = $(this);
// ...that is not the one that just changed.
if( ! $otherSelect.is($changedSelect)) {
// If that other select's selected value is the same as the changed one's
if($otherSelect.selected().first().attr('value') === value) {
alert('...');
}
}
});
}
I didn't try it though, you might have to change a few details in it if it doesn't work.

select2 changing items dynamically

I have two selects that are linked: Each value of the first select determines which items will be displayed in the second select.
The values of the second select are stored in a two-dimension array:
[ [{"id":1,"text":"a"}, {"id":2,"text":"b"},...],
[{"id":"1a","text":"aa"},{"id":"1b","text":"ba"},...],
...
]
The first select value determines the index to be used to populate the second select. So in a 'change' event on the first I should be able to modify the items select-two contains.
Reading documentation I think I need to use the "data" option... but not shure how as the example loads the array data on initialization and it seems to don't work if I try to do the same after initialization.
HTML
Attribute:
<select name="attribute" id="attribute">
<option value="0">Color</option>
<option value="1">Size</option>
</select>
Value:
<select name="value" id="value"></select>
<script>
var data = [ [{"id":1,"text":"black"}, {"id":2,"text":"blue"},...],
[{"id":"1","text":"9"},{"id":"1","text":"10"},...],
];
$('#attribute').select2().bind('change', function(){
// Here I need to change `#value` items.
$('#value').select2('data',data[$(this).val()]); // This does not work
);
$('#value').select2();
</script>
I've made an example for you showing how this could be done.
Notice the js but also that I changed #value into an input element
<input id="value" type="hidden" style="width:300px"/>
and that I am triggering the change event for getting the initial values
$('#attribute').select2().on('change', function() {
$('#value').select2({data:data[$(this).val()]});
}).trigger('change');
Code Example
Edit:
In the current version of select2 the class attribute is being transferred from the hidden input into the root element created by select2, even the select2-offscreen class which positions the element way outside the page limits.
To fix this problem all that's needed is to add removeClass('select2-offscreen') before applying select2 a second time on the same element.
$('#attribute').select2().on('change', function() {
$('#value').removeClass('select2-offscreen').select2({data:data[$(this).val()]});
}).trigger('change');
I've added a new Code Example to address this issue.
I'm successfully using the following to update options dynamically:
$control.select2('destroy').empty().select2({data: [{id: 1, text: 'new text'}]});
Try using the trigger property for this:
$('select').select2().trigger('change');
I fix the lack of example's library here:
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.js">
http://jsfiddle.net/bbAU9/328/
For v4 this is a known issue that won't be addressed in 4.0 but there is a workaround. Check https://github.com/select2/select2/issues/2830
In my project I use following code:
$('#attribute').select2();
$('#attribute').bind('change', function(){
var $options = $();
for (var i in data) {
$options = $options.add(
$('<option>').attr('value', data[i].id).html(data[i].text)
);
}
$('#value').html($options).trigger('change');
});
Try to comment out the select2 part. The rest of the code will still work.
if you are looking a code that is changing another dropdown data by fetching data from server side(Api). You should try this one.
$('#attribute').on('change', function (e) {
$.post("../api", { id: e.val }).done(resp => {
$("#value").select2('destroy').empty();
resp.map(o => $("#value").append("<option value=\"" + o.Value + "\">" + o.Text + "</option>"));
$("#value").select2();
});
});

Categories