Adding new value and selecting clears previous selections - Select2 multiple - javascript

After some fun and games I finally worked out how to dynamically (on button press) add and select a new value to a multiple Select2 select control populated from an MVC model on page load...
<select id="topicMaintMultiSelect" multiple="multiple" name="SelectedMaintTopic" tabindex="18" required="required">
#foreach (var topic in Model.SystemTopics.AvailableTopics)
{
<option value=#topic.Value selected=#topic.Selected>#topic.Text</option>
}
</select>
...and...
function addTopic() {
var newTopic = $("#NewTopic").val();
var select = document.getElementById("topicMaintMultiSelect");
var opt = new Option(newTopic, newTopic);
select.options[select.options.length] = opt;
opt.setAttribute("selected", "selected");
$("#topicMaintMultiSelect").val(newTopic).trigger("change");
$("#NewTopic").val("");
}
...but I cannot work out how to stop it from clearing the previously selected values.
I've tried a variety of suggested solutions, most of which are based on pushing a value into the select2 data but none of these seem to work, not sure why though.
Thoughts/suggestions, please.

Remove the call to .val(newTopic). That is what is clearing the previously selected values.
Adding an option that is marked as selected and triggering a change event is enough to change the value.
var newTopic = $('#NewTopic').val();
var $option = $('<option></option>').val(newTopic).text(newTopic).prop('selected', true);
$('#topicMaintMultiSelect').append($option).change();
jsfiddle for Select2 v4
jsfiddle for Select2 v3.5.3

Related

Proper way to select multiple options from <select> form field using CasperJS/PhantomJS

I am automating testing of a web page in which there exists two multi select fields on a form. The one on the left contains a list of country names, the one on the right contains the ones you have selected. Countries can exist on one list but not the other. When you click a country it moves to the other list (you get the idea). When the form is submitted the values in the POST look like this (from chrome inspection):
data[Campaign][unselected_country_codes]:
data[Campaign][unselected_country_codes][]:AF
data[Campaign][unselected_country_codes][]:AX
data[Campaign][unselected_country_codes][]:AL
data[Campaign][unselected_country_codes][]:DZ
data[Campaign][unselected_country_codes][]:AS
data[Campaign][unselected_country_codes][]:AD
data[Campaign][unselected_country_codes][]:AO
data[Campaign][unselected_country_codes][]:AI
data[Campaign][unselected_country_codes][]:AG
data[Campaign][unselected_country_codes][]:AR
... (ALL countries not selected are in this list)
data[Campaign][country_codes]:
data[Campaign][country_codes][]:US
data[Campaign][country_codes][]:AQ
data[Campaign][country_codes][]:BD
... (this part contains the ones we have selected)
and here is what the HTML looks like for the select list of the countries you want included:
<select name="data[Campaign][country_codes][]" multiple="multiple" id="CampaignCountryCodes" data-quicklist-ref="CampaignCountryCodes_quick" data-alter-ref="CampaignCountryCodes_alter">
<option value="US" selected="selected">United States</option>
<option value="AQ" selected="selected">Antarctica</option>
<option value="BD" selected="selected">Bangladesh</option>
</select>
What I don't understand is, how would I set those form values at the time of testing? I don't really understand the <select> attribute of a form comes through as an array of values or what? I would like to be able to submit the form and have a list of countries that are on, and a list that are off.
Here is an example of what I do to set other values on the form that works correctly. I really have no idea how to do this for a multiple and that is the question being asked.
This example is a text area that works just great.
casper.waitForSelector(x('//*[#id="some text area"]'),
function success() {
test.assertExists(x('//*[#id="some text area"]'));
this.fill('form#campaign_form', {
'data[Campaign][some_field]': 'include',
'data[Campaign][the_field]': myvar + "\n"
}, true);
},
function fail() { ... }
);
You can move the options from one select to the other:
casper.evaluate(function(){
var values = ["US", "CA"];
var src = document.querySelector('[name="data[Campaign][unselected_country_codes][]"]');
var dest = document.querySelector('[name="data[Campaign][country_codes][]"]');
values.forEach(function(val){
dest.appendChild(src.querySelector('[value="'+ val +'"]'));
});
});
After that you probably still have to select them. Just because the options are present in the select box doesn't mean that they are sent to the server when you submit the form they are in. You need to select the values:
casper.evaluate(function(){
var values = ["US", "CA"];
var src = document.querySelector('[name="data[Campaign][unselected_country_codes][]"]');
var dest = document.querySelector('[name="data[Campaign][country_codes][]"]');
values.forEach(function(val){
dest.appendChild(src.querySelector('[value="'+ val +'"]'));
});
// select intended values
[].forEach.call(dest.options, function(opt){
if (values.indexOf(opt.value) !== -1) {
opt.selected = true;
}
});
// trigger change event to run some page JavaScript
var evt = document.createEvent("UIEvents");
evt.initUIEvent("change", true, true);
dest.dispatchEvent(evt);
});
I suspect all of this is not necessary, because you should be able to select the necessary options as seen in CasperJS/ Javascript Selecting Multiple Options and they should appear in the target select box.

Default Value for Dropdown in JavaScript

I'm using JavaScript for an editable table in Bootstrap. Three of the columns are dictated by dropdown values. When the values are "saved" they are converted into their proper text values, but I'm having trouble keeping their saved dropdown choices as the "default" when they come back to edit.
For example:
They enter '3' in their dropdown and save it. If they want to go back and edit (likely another field in the table), the dropdown that once held 3 now goes back to the default of 1.
Here's my code for edit:
function Edit() {
var par = $(this).parent().parent(); //tr
var tdDate = par.children("td:nth-child(1)");
var tdCellNum = par.children('td:nth-child(2)');
var tdButtons = par.children("td:nth-child(3)");
tdDate.html("<input type='date' id='txtDate' value='"+tdDate.html()+"'/>");
tdCellNum.html("<select id='txtCellNum'><option value=1>1</option>
<option value=2>2</option><option value=3>3</option></select>");
tdButtons.html("<img src='save.png' class='btnSave'/>");
Any idea on how to get the value from tdCellNum to display as the default in the dropdown?
I've tried setting the value of select =tdCellNum and tdCellNum.val and using Number to convert the object to a number.I've also tried setting a var=tdCellNum with the rest of the variables, then document.getElementById("tdCellNum").value=copyValue.html(); along with tdCellNum.val=copyValue but all to no avail.Any ideas?? Thanks!
Better to create the element and append it. This way you can use .val() to select the option.
var sel = $("<select id='txtCellNum'><option value=1>1</option><option value=2>2</option><option value=3>3</option></select>");
sel.val(tdCellNum.text());
tdCellNum.empty().append(sel);
You can use tdCellNum.text() to get the value in the field.
Then you could do:
tdCellNumInt=tdCellNum.text();
tdCellNum.html("<select id='txtCellNum'><option value=1>1</option> <option value=2>2</option><option value=3>3</option></select>");
tdCellNum.find("option[value='"+tdCellNumInt+"']").prop("selected",true);

Select2 multiple-select - programmatically deselect/unselect item

I have a select2 list and a set of external buttons. I wanted to click the external buttons and unselect corresponding items in the select2 list. I know I can do item selection from external value using the command
$("#external_btn").click(function() {
$("#select2").val("CA").trigger("change");
});
So when I click on the "external_btn" button, the "ca" item will be selected on the select2.
But how I can do item unselection? Thanks.
There does not appear to be a built-in function to programmatically deselect/unselect an option from a multiple-select Select2 control. (See this discussion.)
But you can get the array of selected values, remove the value from the array, and then give the array back to the control.
Select2 v4:
The following code works for Select2 v4. It also works for Select2 v3 as long as the control is backed by a <select> element, rather than a hidden input element. (Note: When using Select2 v4, the control must be backed by a <select> element.)
var $select = $('#select');
var idToRemove = 'c4';
var values = $select.val();
if (values) {
var i = values.indexOf(idToRemove);
if (i >= 0) {
values.splice(i, 1);
$select.val(values).change();
}
}
JSFiddle for Select2 v4
JSFiddle for Select2 v3
Select2 v3:
The following code works for Select2 v3, regardless of whether you back the control with a <select> element or a hidden input element.
var $select = $('#select');
var idToRemove = 'c4';
var values = $select.select2('val'),
i = values.indexOf(idToRemove);
if (i >= 0) {
values.splice(i, 1);
$select.select2('val', values);
}
JSFiddle for Select2 v3, using <select> element
JSFiddle for Select2 v3, using hidden input element
As you've indicated in your question, you can modify the state of the underlying select element and then trigger a change. So then you can simply deselect an option in the same way you might with a regular select.
Assuming an option of value "val", the following code would deselect it:
$("#select option[value=val]").prop("selected", false) // deselect the option
.parent().trigger("change"); // trigger change on the select
http://jsfiddle.net/9fD2N/3/
I don't see anything to "deselect" an element. But, you can get the list of currently selected elements, remove your element and then set the value.
http://jsfiddle.net/wLNxA/
$("#e8_2").select2({
placeholder: "Select a state"
});
$('#removeBtn').click(function () {
// get the list of selected states
var selectedStates = $("#e8_2").select2("val"),
index = selectedStates.indexOf('NV'); // we're removing NV, try to find it in the selected states
if (index > -1) {
// if NV is found, remove it from the array
selectedStates.splice(index, 1);
// and set the value of the select to the rest of the selections
$("#e8_2").select2("val", selectedStates);
};
});
It's works.
$('{SELECTOR}').val('').trigger('change')
If you do not have any other event listener action on select option better :
$("#select2").val("CA").attr('checked', 'checked'); // to check
$("#select2").val("CA").removeAttr('checked'); // to un-check

Get each selected value using chosen jquery plugin

I'm using Chosen Multiple Select
What I want to do is that if user selects any option I want that value and then I will do some functionality depending on that value.
In chosen without multiple select i can get selected value by using foll. code
$(".selectId").chosen().change(function(){
selectedValue = $(this).find("option:selected").val();
});
But in multiple select I get the first selected value again n again
can anybody help me by finding the current selected value in multiple select element??
The Chosen documentation mentions parameters for getting the most recently changed variables.
Chosen triggers the standard DOM event whenever a selection is made
(it also sends a selected or deselected parameter that tells you
which option was changed).
So, if you just want the most recent option selected or deselected:
$(".selectId").chosen().change(function(e, params){
// params.selected and params.deselected will now contain the values of the
// or deselected elements.
});
Otherwise if you want the whole array to work with you can use:
$(".selectId").chosen().change(function(e, params){
values = $(".selectId").chosen().val();
//values is an array containing all the results.
});
Short answer:
You just do this: var myValues = $('#my-select').chosen().val();
Full example:
If you have a select-multiple like this:
<select id="my-select" class="chzn-select" multiple data-placeholder="Choose one or more values...">
<option value="value1">option1</option>
<option value="value2">option2</option>
<option value="value3">option3</option>
</select>
You can get the selected values in an array to doing the following:
// first initialize the Chosen select
$('#my-select').chosen();
// then, declare how you handle the change event
$('#my-select').chosen().change(function(){
var myValues = $('#my-select').chosen().val();
// then do stuff with the array
...
});
your code is gettin the correct selected value.. but since its multiple you need to use loop..or use map to get the selected value and push it into array..
try this
$(".selectId").chosen().change(function(){
var selectedValue = $.map( $(this).find("option:selected").val(), function(n){
return this.value;
});
console.log(selectedValue ); //this will print array in console.
alert(seletedValue.join(',')); //this will alert all values ,comma seperated
});
updated
if you are getting commaseperated values then use split()
var values= $(".selectId").val();
$.each(values.split(',').function(i,v){
alert(v); //will alert each value
//do your stuff
}
try this
$('.selectId:selected').each(function(i, selected) {
var value = $(selected).val();
var text = $(selected).text();
});
The Chosen documentation mentions parameters for getting the most recently changed variables.
$(".CSS Selector").chosen().change(function(e, parameters) {
// params.selected and params.deselected will now contain the values of the
// or deselected elements.
});
This is how I've got it to work. In my html, I've this
<select data-placeholder="Choose a Country..." class="form-control chosen-select" multiple tabindex="4">
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="CHINA">CHINA</option>
</select>
Then javascript
// apply chosen-js to the DOM, and store it in a variable.
var chosen = $(".chosen-select").chosen({
no_results_text: "Oops, nothing found!"
});
// inside the change event, we get the value by calling chosen.val()
chosen.change(function() {
console.log('selected tags are', chosen.val());
});

Add or remove dropdown elements from the javascript or jquery

I have dropdownlist whose value is filled using the value of the other drop down. The problem here is that i need to bind the value of the second when the value of the first changes. I need to do it from the javascript.
Only thing i need to do is remove and add the select options in the second dropdown as the first dropdown changes.
How can i do this?
Thanks in advance.
Not too sure exactly what you want with the limited information provided but here is a solution that I think you are looking for:
HTML:
<select id="primary">
<option value="one">One</option>
<option value="two">Two</option>
</select>
<select id="secondary"></select>
jQuery:
var opts = {
'one':['a','b','c'],
'two':['d','e','f']
};
$('#primary').change(function(){
var select = [];
$.each(opts[this.value], function(k, v){
select.push('<option>'+ v +'</option>');
});
$('#secondary').html(select.join(''));
});
Demo: http://jsfiddle.net/28TQZ/
$("#dropdownlist1").change(function () {
var selected = $("#dropdownlist1 option:selected");
//clear
$("#dropdownlist2").html("");
$("#dropdownlist2").append($("<option/>").text(selected.text()).val(selected.val()));
})
Create all the drop downs you need, but only add options to the first one. The next ones only have a "default" value.
On selecting the first drop down, you use jQuery to get the values for the second drop down, based on the value selected in the first drop down:
$.post('ajax/aj_populate2nddropdown.php', $("#firstdropdown").val(), function(result) {
$('div.placedaround2nddropdown').html(result);
});
The file ajax/aj_populate2nddropdown.php collects the values of the second drop down, and returns them, inserted as options into the dropdown.
One simple way to do it is to just have a main dropdown and a bunch of secondary dropdowns that start hidden. when you choose something from the first, then you unhide the related second one
Try this If you are trying at client side
Replace your controls with asp.net server controls

Categories