select2 predefined rendered item with ajax - javascript

I can easily retrieve and format AJAX data to work with Select2, like this
function formatItem (item) {
if (!item.id) {
return item.text;
}
var _item = '<span class="' + item.deleted +'"><i class="fa fa-user"></i> ' + item.doctor + ', <small>' + item.sex + ' (' + item.user + ')</small></span>';
return $(_item);
}
var tabSelect = $('#t');
tabSelect.select2({
ajax: {
url: '../ajax/results.php',
data: function (params) {
return {
search: params.term,
page: params.page || 1
};
}
},
templateResult: formatItem,
templateSelection: formatItem
});
So far so good: <select> items are rendered correctly as HTML, with the nice Font-Awesome icon and the <small> tag.
User now selects an item and submits the (search) form. Of course I'd like to mark the current item as selected, and here comes the trouble.
Select2 docs have a way to predefine an AJAX retrieved item, but this works for simple text and not for rendered items with all the HTML bells and whistles
So, when adapting the provided example:
$.ajax({
type: 'GET',
url: '../ajax/results-selected.php', // url to retrieve a single item
data: {
iData: [here goes the ID for retrieving single item]
}
}).then(function (data) {
// create the option and append to Select2
var item = data.results[0];
console.log(item);
var option = new Option(item, item.id, true, true);
tabSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
tabSelect.trigger({
type: 'select2:select',
params: {
data: data
}
});
});
I get the HTML rendered item, but with a series of undefined (please notice that console.log(item) returns the expected result: in other words, I have the fields but have no idea how to render them)
I tried lot of things, but none of them work, i.e.:
var option = new Option(formatItem(item), item.id, true, true);
I read around but could not find a valid solution working: please, any help?

I managed it to work by returning the whole HTML snippet in the JSON response (as text item)
// the JSON response
{
"results": [
{
"id": "1234",
"text": "<span class=\"\"><i class=\"fa fa-user\"></i> Doe John, <small>Mr. (Site Owner)</small></span>"
}
]
}
// the updated snippet
$.ajax({
type: 'GET',
url: '../ajax/results-selected.php', // url to retrieve a single item
data: {
iData: [here goes the ID for retrieving single item]
}
}).then(function (data) {
// create the option and append to Select2
var item = data.results[0];
console.log(item);
var option = new Option(item.text, item.id, true, true);
tabSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
tabSelect.trigger({
type: 'select2:select',
params: {
data: data
}
});
});

Related

How to add items to selectize field

Could you please help me cause I'm stuck :/ I have a snippet where I want to add data from API to my selectize field. I prepared this selectize field manually in the system cause I have to. Here I just want to pass this data. Here is my snippet:
function getCarriersData() {
const queryType = "GET";
const funcName = "getcarriersdata";
const queryUrl = globalDataObject.appRootPath + "api/extension/" + funcName;
$.ajax({
url: queryUrl,
type: queryType,
success: function(result) {
const przewoznik = $('span[data-inputattrname="KZ_Kurier_DP_przewoznik"]').find('select')[0].selectize;
if (Object.keys(przewoznik.options).length == 0) {
console.log('That part works')
$.each(JSON.parse(result), function(i, item) {
przewoznik.addOption({ value: item.Name, text: item.Name });
przewoznik.setValue(item.Name, false)
});
}
}
});
}
I receive data from API and I parse it to multiple objects (JSON.parse), but still doesn't work.

Refreshing JSON input in Select Box after Resolve / Promise in Sweet Alert 2

I have a sweet alert 2 select input box that is populated by an external JSON file
var inputOptionsPromise = new Promise(function(resolve) {
setTimeout(function() {
$.getJSON("http://localhost/so/categories.json", function(data) {
resolve(data)
});
}, 500)
})
This JSON file contains a list of categories one can choose, or a last option of key value pair of "Add Category +"
title: 'Select Category',
input: 'select',
inputClass: 'swal-select-category',
inputPlaceholder: 'Please Select',
inputOptions: inputOptionsPromise,
inputValidator: (value) => {
return new Promise((resolve) => {
if (value === '') {
resolve('You need to input a category!');
} else if (value === 'Add Category +') {
alertify.prompt('Category Name', '', function(evt, value) {
$.ajax({
type: "POST",
async: false,
url: 'http://localhost/sa/resources/scripts/addcategory.php',
data: {
data: value
},
success: function() {
alertify.success('Category ' + value + ' Added.');
resolve(value + ' Category Added');
},
failure: function() {
alert("Error Adding Category!");
resolve('Error!');
}
});
}, function() {
resolve('You need to input a category!');
});
} else {
resolve()
}
})
}
As you can see if the user chooses the select option Add Category +, a pop-up input box that performs an AJAX request to a PHP page to append whatever input (new Category) to this JSON file.
This works as intended, and a user can either choose a pre-existing category in the JSON file or add a Category to the JSON file using the mentioned option.
After all this work, though, an unfortunate pitfall in this case, is that the input box/JSON is not refreshed once a new Category is appended to the JSON file.
If a user refreshes the page, or exits the sweet alert 2 queue again, it reloads the JSON and displays the new category inputted -- but not whilst in the sweet alert 2 existing dialogue box that the user is expecting to choose his or her category in.
Is it possible to refresh my inputOptionsPromise var to get the new JSON values within the inputValidator or Resolve?
I've added a custom class to the sweet alert 2... must I use some hack-ish jquery solution to possibly refresh the select options or is there a better way to go about getting refreshed JSON data while entering and exiting a promise/resolve?
I just ended up adding this bit of jQuery to insert the option value as the second select option. Works fine and doesn't require a json refresh. Probably better.
$('.swal2-select option:first').after($('<option />', { 'value': value, text: value }));
$('.swal2-select option[value="' + value + '"]').attr('selected','selected');
or
$.ajax
({
type: "POST",
async: false,
url: 'http://localhost/sa/resources/scripts/addcategory.php',
data: { data: value },
success: function () {
alertify.success('Category ' + value + ' Added.');
$('.swal2-select option:first').after($('<option />', { 'value': value, text: value }));
$('.swal2-select option[value="' + value + '"]').attr('selected','selected');
resolve(value + ' Category Added');
},
failure: function() {
alert("Error Adding Category!");
resolve('Error!');
}
});

Select2: how to set "title" property of a multiple select tag?

I noticed that there's a mousehover title that is set on the elements when using select: multiple. However, I seem to have no control over it. What I want to do is to set the tag name to the product name, and the hover title to the product code. I tried the following:
$('#repair_parts').select2({
multiple: true,
ajax: {
type: "POST",
url: "/admin/part/show",
dataType: "json",
cache: true,
data: function (params) {
var query = {
data: params.term
}
return query;
},
processResults: function (data) {
results = [];
for (i = 0; i<data.length; ++i) {
results[i] = {title: data[i].code, id: data[i].id, text:data[i].code+": "+data[i].name};
}
return {results: results};
},
},
templateSelection: function (data, container) {
container.prop('title', data.title);
return text;
}
});
But to no avail. The title is still the same.
Turns out what I did was just fine, however, the PHP script that loaded the options from the database would not have the correct title tags. I used JavaScript to change the formatting of the tag and done.

Unable to select the newly added selectize components post an ajax call

Unable to select the newly added selectize components post an ajax call
I have pre populated the options with the currently selected options, and trying to retrieve more option with an ajax call from the server.
My server returns data like this but I am not sure what to do with this data
[{"id":303,"name":"Short Sleeve Opening"}]
I've tried using the addOption and refreshOptions methods, but they doesn't seem to work.
Below is the piece of code which is invoking the selectize component.
$(function () {
$select_options = $('select').selectize({
plugins: ['restore_on_backspace', 'remove_button', 'drag_drop'],
delimiter: ',',
persist: false,
create: function (input) { // I am not sure if this is of any use, as I never found the control to enter in this part of code during debugging.
return {
value: input,
text: input
}
},
load: function (query, callback) {
if (!query.length) return callback();
$.ajax({
dataType: 'json',
url: '/measurement_tags/autocomplete_key?q=' + encodeURIComponent(query),
error: function () {
callback(); //Not sure what the callback should be, documenation is not self explanatory
},
success: function (res) {
//Added this callback to add the new options to the list, it is adding the new options to the list but I can't select them at all
//Moreover, second time I try to use autocomplete it doesn't work. The control doesn't reach the load method, and no error observed in console
for (index in res) {
$('.selectize-dropdown-content').append('<div class="option" data-selectable="" data-value="' + res[index].id + ' ">' + res[index].name + '</div>');
}
}
});
}
});
});
What is the exact way to add the new options to the list permanently?
Finally achieved this after wasting whole day:
$(function () {
$select_options = $('select').selectize({
plugins: ['restore_on_backspace', 'remove_button', 'drag_drop'],
delimiter: ',',
persist: false,
options: [],
load: function (query) {
$.ajax({
dataType: 'json',
url: '/measurement_tags/autocomplete_key?q=' + encodeURIComponent(query),
success: function (res) {
updateOptions(res);
}
});
}
});
var updateOptions = function (newOptions) {
var selectize = $select_options[0].selectize;
for (index in newOptions) {
selectize.addOption({
value: newOptions[index].id,
text: newOptions[index].name,
});
}
selectize.refreshOptions();
}
});

select2 version 4 ajax data : results not appearing in control

Since I have switched to version 4 of the select2 plugin, my ajax calls do not work anymore.
I get a response in the form of an array which prints ok in the console but the results don't show in the select2 control.
http response :
{"results":{"id":"ok","term":"ok","description":"ok"}}
My code :
$(function(){
$('#appbundle_marketplace_product_ingredient_barcode').select2({
minimumInputLength: 3,
ajax:
{
delay: 250,
url: "{{ path('search_barcode') }}",
dataType: 'json',
debug: true,
data: function (params) {
// console.log(params.term);
return {barcode: params.term};},
processResults: function (data) {
console.log(data);
return data;
}
}
});
});
the data printed in the console is the following object :
Object {results: Object}
results: Object
description: "ok"
id: "ok"
term: "ok"
__proto__: Object
__proto__: Object
How can I have the select2 display a result in the dropdown, then click the result to have it selected ?
Thanks a lot,
Great question, same issue I ran into.
I had a similar issue, working in Wordpress. I had to update my php to return this:
// This prepared SQL query returns objects, so I thought I was fine
$partList = $wpdb->get_results( $sql );
// echo json_encode( $partList ); <- worked, but not quite right...
// Select2 wanted an array of items, so I added this
$jsonItems = array("items"=>$partList);
echo json_encode( $jsonItems );
In my JS I have this...
function formatPartSelection(ajaxData){
return ajaxData.commonName || ajaxData.text;
}
function formatAjaxResponse (ajaxData){
if(ajaxData.loading) return ajaxData.text;
var markup = '<div class="clearfix select2-result-selectable" style="border-bottom:solid; border-bottom-color: #D3D3D3">' +
'<div class="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-10"><span style="font-weight: bold;">' + ajaxData.fieldOne + ' | ' + ajaxData.text + '</span></div>' +
'</div>';
if (ajaxData.description) {
markup += '<div class="col-sm-10">' +
'<div class="clearfix">' +
'<div><i>' + ajaxData.description + '</i></div>';
}
markup += '</div><br/></div>';
return markup;
}
$.fn.select2.amd.require(
["select2/core", "select2/utils", "select2/compat/matcher"],
function (Select2, Utils, oldMatcher) {
});
$('.myClass').select2({
placeholder: "Select part(s)...",
minimumInputLength: 3,
multiple: true,
ajax: {
url: url_to_your_php,
delay: 250,
type: "POST",
dataType: 'json',
data: function (params) {
var queryParameters = {
action: 'my_enqued_wp_ajax',
searchStringValue: params.term
}
return queryParameters;
},
processResults: function (data) {
console.log(data);
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
templateResult: formatAjaxResponse,
templateSelection: formatPartSelection
});
The above code allowed me to get the list of items to select from working, but I couldn't actually click any of them. Many hours later, I found this answer which helped me to actually be able to select one of the values in my Select2 dropdown list:
https://stackoverflow.com/a/29082217/4266699
*Note, I had the luxury of creating a column in my DB called ID, so I was able to fix this on the backend.
Hope this helps!

Categories

Resources