select2 change event without removing already selected options - javascript

I'm using select2 with multiple options and programmatic access to select also with a button. It works fine but when I click on the button all previously selected values are removed and only the value from the clicked button gets selected. Since I'm using multiple select it would make sense to add the clicked value and leave the previously selected without removing them... Is there another event to trigger besides "change" that does not remove values but adds them instead?
<select id="id_entities" class="js-example-programmatic" style="width:100%" multiple="multiple">
</select>
<td><button id="prefix_{{teu.entity_id}}" class="js-programmatic-set-val" value="{{teu.entity_id}}" name="{{teu.entity}}"><i class="fa fa-plus"></i></button></td>
<td>{{teu.entity}}</td>
<td>{{teu.user}}</td>
<script >
$(".js-example-programmatic").select2({
minimumInputLength: 2,
placeholder: "Select entities...",
allowClear: true,
multiple:true,
delay: 250,
tags:false,
ajax: {
url: '/entities/search/autocomplete/',
dataType: 'json',
data: function (parms, page) { return { title: parms.term }; },
},
});
</script>
<script>
var $example = $('#id_entities');
$("button[id^='prefix_']").click(function(){
value = $(this).attr('value');
value_name = $(this).attr('name')
if ($('#id_entities option[value="'+value+'"]').length > 0) {
}
else {
$("#id_entities").append('<option value="'+value+'">'+value_name+'</option>');
}
$example.val(value).trigger("change");
});
</script>

well, without seeing a working demo, I assume what you want is to append tags on to a select2 without erasing what tags/multi-selects are already there? If so, you would need to evaluate the element value, and append new vals rather than just calling $example.val(value), which replaces the value of said element
var data = $(test).select2('data');
data.push({id:5,text:"fixed"});
$(test).select2("data", data, true); // true means that select2 should be refreshed
Seels like a duplicate of SELECT2 -> Add data without replacing content

Related

django-select2 programatically setting value

I'm using Django-select2 to show select2 widgets on my forms.
On one of these form select-fields I want to user to be able to set the value by clicking a link containing a suggestion.
My javascript looks like:
<script type="text/javascript">
$( document ).ready(function() {
// When the topicSuggestion is clicked, populate the select2 field with that value.
$('#topicSuggestion').on('click',function (e) {
var value = {{ object.suggestion.topic.id }};
$('#id_topic').val(value).trigger('change');
});
});
</script>
This isn't quite working as expected though. Instead of nicely populating the value, this is the behaviour I see:
Click the link, nothing happens
Select a random value from the list, and click the link. The select seems to clear
Select the desired value once, now click a random value and click the link. Now the value populates correctly
I can imagine this is related to my non-existing js skills. Could someone be kind enough to help me clear this up on this newyears day?
As we can see in https://github.com/codingjoe/django-select2/discussions/145
the items are loaded async. So if you want to pre-populate, you need to add the value first.
The select2 docs explain this: https://select2.org/programmatic-control/add-select-clear-items#create-if-not-exists
The answer in this case is:
$( document ).ready(function() {
// When the topicSuggestion is clicked, populate the select2 field with that value.
$('#topicSuggestion').on('click',function (e) {
$( "#topicSuggestion" ).css( "border", "9px solid red" );
var data_id = {{ object.suggestion.topic.id }};
var data_name = "{{ object.suggestion.topic.name }}";
// Set the value, creating a new option if necessary
if ($('#id_topic').find("option[value='" + data_id + "']").length) {
$('#id_topic').val(data_id).trigger('change');
} else {
// Create a DOM Option and pre-select by default
var newOption = new Option(data_name, data_id, true, true);
// Append it to the select
$('#id_topic').append(newOption).trigger('change');
};
});

Removing multiple select options and replace with new ones

I have a select tag like :
<span id="reportProjectSelector">
<span>Reporting Project:</span>
<select id="reportProjectDropdown" onChange="loadChartWithData();" multiple="multiple"></select>
</span>
and
$(function() {
$('#reportProjectDropdown_${widgetId}').multiselect({
includeSelectAllOption: true
});
});
Here I have multiple dropdown chain of other dropdowns which are parents of 'reportProjectDropdown'. For simplicity let's consider just one 'Project'. So now we have 'Projects', on change of which 'Reporting Projects' filter is triggered. Currently the Reporting project filter doesn't change and replace new values (basically null or no values which are replaced by a value like 'No Reporting Projects' in the dropdown)
I have tried removing the previous values but with no luck. Here is the function that I am expecting will do the job.
function setDependentProjects (data, widgetId) {
$('#reportProjectDropdown').find('option').remove().end();
if(jQuery.isEmptyObject(data)) {
let newOption = new Option("No Projects", 0, true, true);
$('#reportProjectDropdown').append(newOption);
} else {
let selected = true;
for(let key in data) {
selected = "${defaultDependentProject}" == data[key];
let newOption = new Option(data[key], key, selected, selected);
$('#reportProjectDropdown').append(newOption);
selected = false;
}
}
loadChartWithData_${widgetId}(); //renders data as per the previous filters
}
Am I missing something or removing the elements incorrectly ?
You need to refresh the jQuery multiselect instance after every change. You can do that by using $('#reportProjectDropdown').multiSelect('refresh');
See also the documentation: jQuery multiselect

How to filter a JSON array in autocomplete jquery and show a dynamic value in JavaScript?

I have successfully implemented the jQuery Autocomplete function in my HTML input filed, it returns an array of JSON objects, what I would like to achieve is the following:
click on an item of the dropdown list
filter such item's string to get only the objID string.
So, here's my js code:
$.ajax({
url: "<?php echo $pointerClass ?>.json",
type: "POST",
dataType: "JSON"
}).done(function(data){
var jsonData = data;
var arr = new Array();
var keys = Object.keys(jsonData);
for(var i=0; i<keys.length; i++){
var key = keys[i];
var jString = JSON.stringify(jsonData[key]);
arr.push(jString);
}// ./ for
console.log('arr: ' + arr[0]);
// autocomplete jquery function
$( "#ar-type-pointer-objID" ).autocomplete({
source: arr,
minLength: 1
});
});
Here's a screenshot of my drop-down menu:
As you can see by the red frame, I need to click on an item and pass only the "objID" value to my input field, so it'll be "qO19zg8mV4" since I'm clicking on the row in the red square.
Here's how my input should look like after clicking on a drop-down's row:
According to the autocomplete documentation, you have two interesting events: select and close.
select is
Triggered when an item is selected from the menu. The default action is to replace the text field's value with the value of the selected item
close is:
Triggered when the menu is hidden. Not every close event will be accompanied by a change event.
Select has two parameters:
event
ui
ui is an object like this:
item: {
label: string,
value: string
}
Not sure where you will get your JSON, probably value, so I assume that...do a console.log to be sure of it!
You should rewrite with something like
$( "#ar-type-pointer-objID" ).autocomplete({
source: arr,
select: function(event, ui) {
const target = event.target;
const val = JSON.parse(ui.item.value); // Check if decode is needed or is already passed as an object
jQuery(target).val(val.ObjID);
event.preventDefault();
return false;
}
});
We prevent the default, because "The default action is to replace the text field's value with the value of the selected item." and your change in the input field will be lost.
You still have to manage some info by yourself but the idea should be enough!

Get selected value from multiple select on change in dynamic form

I'm currently working on a dynamic form which enables the user to add as many variants as they would like. This form which can be added has a price, size and color. The size and color are select2 select boxes which enable the user to select multiple things. The form:
<div class="col-sm-4">
<label>Kleuren</label>
<select name="colors[{{$i}}][]" id='color-options' class="form-control multiple-select" multiple="multiple">
#foreach($colors as $id=>$color)
<option value="{{$id}}">{{$color}}</option>
#endforeach
</select>
</div>
When looking at the HTML code I have multiple of these forms which go by name: colors[0][], colors[1][], colors[2][] etc.
How do I print the value of a selected new color in a new div? The code which I have thus far:
$(document).ready(function() {
$('.multiple-select').select2({
language: 'nl'
});
$('.summernote').summernote();
var addVariantButton = document.getElementById('addVariant[0]');
addVariantButton.addEventListener('click', function(){
addVariant(0);
});
var colorSelected = document.getElementsByName('colors[0][]');
colorSelected.addEventListener("click", displayColorSelected);
});
function displayColorSelected() {
var selected_value = document.getElementById("color-options").value;
console.log(selected_value);
}
But this only works for the first colors input form, but how can I make this into a more dynamical function to get all colors input?
You can get all selected values in array as below:
function displayColorSelected() {
var selected_value = $("[id='color-options']").toArray().map(x => $(x).val());
console.log(selected_value);
}
Note: id selector will always return single element which will be first with that id. So you're getting value for first select only.
You can use attribute selector ([]) instead which will find every element with given id. So here $("[id='color-options']").toArray() will find every element with id equal to color-options and map(x => $(x).val()) will return only value part from the elements array.
Add all the selects a class ("color-select" for example), and run over all the selects -
$('.color-select').each(function() { console.log($(this).val()); })
You may need to delegate your event listener
document.addEventListener('event',function(e){
if(element){//do something}
})
Since you are using jquery its easier
$(document).on('event','element',function());

Select2 Dropdown Dynamically Add, Remove and Refresh Items from

This drives me crazy! Why cant Select2 implement clear methods or examples on their page how to do simple CRUD manipulation on Select2 :)
i have a select2 which gets data from a ajax call.
<input id="valueg" type="hidden" style="width: 300px;" data-placeholder="Select a Conference" />
$("#valueg").select2({
data: conferences,
allowClear: true,
initSelection: function (element, callback) {
var data = { id: element.val(), text: element.val() };
callback(data);
}
}).on("change", function (e) {
// show data in separate div when item is selected
});
Can some one provide a clear method how to delete and add an item from the Select2.
For example:
I add an item via ajax call to db, and just want to append an option to Select2 and set it as selected.
I remove an item via ajax to db, and want to remove an option from Select2 and have no option selected.
From your example I can see that you attached Select2 plugin to hidden element. In addition you use Ajax call to populate results, so in this case if you need to add a new option to the list you simple call:
$('#valueg').select2('val', 'YOUR_VALUE');
In case of using select element as a container the only way that I found is to reinitialize plugin with new options... Something like this:
var el = $('select[name="type"]', '#details-form');
var temp = el.select2('val'); // save current value
temp.push(NEW_VALUE); // append new one
var newOptions = '<option value="1">1</option><option value="2">2</option>';
el.select2('destroy').html(newOptions ).select2().select2('val', temp);
I did it this way:
var $select2 = $('#valueg').select2(); // getting the select2
var item = 'xyz'; // item to be added
$select2.val(function(i, val) { // val can take function as parameter
val = val || []; // if value is null init val as an array
val.push(item); // add the new item
return val;
}).trigger("change"); //refresh
Hope that helps
I had the same issue. This is how i solved it
This has nothing to do with select2, manipulating the itself seems to work for me
$("#lstService").empty();
for(var i=0;i<data.length;i++){
$("#lstService").append('<option value="'+data[i].service_id+'">'+data[i].service_name+'</option>');
}
In my case, the key thing to add after manipulating the underlying select is:
$selectlist.trigger("change"); //$selectlist is the underlying select element.
Select2 works around the change event on a select, so calling "change" updates the option displayed in the select 2.
It is too late... but this is my solution for people that still have this problem:
html = "";
jQuery("#select_2 option").each(function()
{
html += '<option value="'+jQuery(this).attr("value")+'">'+jQuery(this).text()+'</option>';
});
html += '<option value="NEWVALUE">NEW OPTION</option>';
jQuery("#select_2").html(html);

Categories

Resources