Select2js separate results obtained by ajax call from user input - javascript

I have a select2js select field which retrieves a list of diseases based on user query to a database. The type of select is tags so that if the entry is not in the database, the user can add their own. An example of what it looks like is seen below:
The options below are populated by an ajax call made to a local api to retrieve the diseases from a database.
How can we write: "Suggestions" below the user input or hide the user input from the dropdown (seen above as "IgA ne") so that the user is more likely directed to choose one of the options from the database?
Some sample code:
HTML
<select id="diseases" class="form-control selectmultiple" name="diseases[]" multiple="multiple" aria-describedby="diseasesHelp">
</select>
<small id="diseasesHelp" class="form-text text-muted">If known to appear in certain diseases e.g. Tn syndrome</small>
JS
$('#diseases').select2({
tags: true,
placeholder: 'Select an item',
minimumInputLength: 3,
ajax: {
url: '/diseaseSelector',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
id: item.id
}
})
};
},
}
});

About the "Suggestions" below the user input, you could use Option Group. Using Ajax, the options should be in a Option Group object, in this format:
{
"text": "Group Name",
"children": [] // your options
}
So, in your case :
processResults: function (data) {
return {
results: [{
text: "Suggestions",
children: $.map(data, function (item) {
return {
text: item.name,
id: item.id
}
})
}]
};
},

Related

Select2 - Multi Select Autocompletion - Programmatically population of field

I am using the bundled AUI Select2 Lib in a JIRA 8.13 instance.
What I would like to try is to code an autocompletion field with multiple values. My main components are running so far, but I have some problems while populating the field programmatically via JavaScript.
This my basic setup:
field.auiSelect2(
{
multiple: true,
closeOnSelect: true,
tokenSeparators: [","],
placeholder: PLACEHOLDER,
minimumInputLength: 2,
formatResult: format,
initSelection: function (element, callback) {
callback({id: $(element).val(), text: $(element).val()});
},
ajax: {
url: <...>,
dataType: 'json',
data: function (term) {
return {term: term,};
},
results: function (results) {
return results;
},
quietMillis: 250,
cache: false
},
});
The field population code is the following:
field.val(["A","B","C"]).trigger('change');
But this results in a single entry in the input field value "A,B,C" which is wrapped within a single gray box instead of multiple boxes - one for each passed value.
Any ideas on how to solve this issue? I guess it might be related to the initSelection parameter.
https://codepen.io/aschuma/pen/rNLRLWL
$(field).auiSelect2("data", [{id: "A", text: "A"},{id:"B", text: "B"},{id:"C", text: "C"}]);
https://codepen.io/aschuma/pen/ExyMNJP
This error is because you are using an <input> element instead of a <select> element. When you call this:
field.val(["A","B","C"]).trigger('change');
what you are really doing is setting the value of the <input> field which operates completely separately from select2. An <input> field can only have a single value, so it is likely that jQuery simply calls a standard .join() on the array and then sets the value to that. You can verify this is correct by simply opening a console and running:
console.log(["A","B","C"].join())
which will result in the string "A,B,C". What you might need is a <select> element which can support multiple values. Also note that the latest version of AUI Select2 (9.1.4) uses select2 version 3.4.5 instead of the latest version (4.0.13 as of the time of this post).
You could also set the data on the select2 instance itself like so:
$(field).auiSelect2('data', [
{id: 'A', text: 'A'},
{id: 'B', text: 'B'},
{id: 'C', text: 'C'},
]);
Found this thread because we had the same problem. I can confirm that it's also posible using elements if you use the following code.
AJS.$('#customfield_14882').auiSelect2(
{
multiple: true,
closeOnSelect: true,
tokenSeparators: [","],
placeholder: PlaceHolder,
minimumInputLength: 1,
allowClear:true,
initSelection: function (element, callback) {
var arr = $(element).val().split(',');
var res=[];
for(var i=0;i<arr.length;i++){
res[i]={id:arr[i],text:arr[i]};
}
callback(res);
},
ajax: {
url: "<url>",
dataType: 'json',
data: function (term) {
return {term: term};
},
results: function (results) {
return {results:results};
},
quietMillis: 250,
cache: false
},
});

how to call query call back data to data attribute select2

$('#placeSelect').select2({
width: '100%',
allowClear: true,
multiple: true,
maximumSelectionSize: 1,
placeholder: "Click here and start typing to search.",
data: function(query) {
queryData{!randomJsIden}(query);
},
matcher: function (term, text) {if (text.toUpperCase().indexOf(term.toUpperCase()) == 0){return true;}return false;}
});
function queryData{!randomJsIden}(query){
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.AutoCompleteV2_Con.getData}','{!sObjVal}','{!labelFieldVar}','{!valueFieldVar}',query.term,
function(result, event){
//if success
if(event.status){
var data = {results:[{ id: 1, text: "Ford" },
{ id: 2, text: "Dodge" },
{ id: 3, text: "Mercedes" },
{ id: 4, text: "Jaguar" }]}
query.callback( data);
}
},
{escape: true}
);
}
</script>
How to initialize query call back data to data attribute in select2 .
I cannot use data directly .In above example i am using sample data .
query : function(query){
queryData{!randomJsIden}(query);
}
I want to replace this by data attribute like this : the below one is not working
data : function(query){
queryData{!randomJsIden}(query);
}
here is the fiddle :
http://jsfiddle.net/Lnf8j/303/
Let me know any ideas from you
There are couple of issues in your code
you cannot name a function using flower braces as it is reserved notation symbol in javascript function queryData{!randomJsIden}(query), instead name it as function queryData(query){ ... }
if your adding a callback for data of your select2 then you need to return that data constructed from queryData() function.
data: function(query) {
return queryData(query);
},
function queryData(query){
...
return data;
}
If i'am not wrong,data is sourced to select2 via asynchronous call inside queryData(), which means the data is returned at unpredictable time,so you need to restrict the user from accessing the select2 component until data is feeded to it.
which means you either need to prefetch the data or disable the select2 field until data is returned from remote call.
Working Demo # JSFiddle

Select2 - Can't select a value?

Release version (Select 4.0.1)
HTML
<select id="search_customers" style="width: 300px;"></select>
Javascript:
$("#search_customers").select2({
multiple: false,
allowClear: true,
ajax: {
url: "#Url.Action("
SearchCustomers ", "
Home ")",
dataType: 'json',
delay: 250,
data: function(params) {
return {
id: params.term, // search term
};
},
processResults: function(data, params) {
return {
results: data
} // Data is a List<T> of id an text
},
}
});
The dropdown works, and I can see my records, however, when I click on one of the options the box closes, and the selected record isn't shown. My box looks like this
I've tried everything I can think of. The issue appears in all browsers. The data being return is a list of id/text pairs.
Controller code
var customers = this.service.SearchCustomers(id).Select(x => new { id = x.CustomerID, text = x.CustomerName }).ToList();
return Json(customers, JsonRequestBehavior.AllowGet);
My customer ID's had leading spaces for some reason. (Old ERP system), so adding a .Trim() call to the select statement on the customer ID fixed it. Apparently select2 doesn't like " 56", but "56" is fine!

Adding additonal Selected value in Select2 on button click?

The scenario is, I need to append a value (a selected Value) to select2 by just clicking a button. What happen is if I click my button, the other values I selected are gone/cleared.
Only 1 value is selected which is the value in my button function. I could select multiple values when typing directly to my select2 textbox, but then if i clicked the button, its value doesn't add to select2.
How do i append a value or push an additional value to data already selected in select2 on my click Button? a new value should be added to select2 selected values everytime I click the button.
I hope my code below, and my description to what im looking for kinda help you guys. Thank you.
I'm using Northwind DataBase, for testing it. (Robert King is under Employee Table)
<input type="button" onclick="Passvalue();"/>
<input type="text" id="eq" name="eq" style="width: 200px;" />
<script>
$(function () {
$("#eq").select2({
minimumInputLength: 3,
multiple: true,
ajax: {
url: '/Employee/GetAllEmployees/',
dataType: 'json',
type: "GET",
data: function (searhTerm) {
return { query: searhTerm };
},
results:
function (data) {
return { results: data};
},
},
initSelection: function (element, callback) {
var id=$(element).val(); //element value will be 'Robert';
if (id!=="") {
$.ajax('/Employee/GetAllEmployees/', {
data: {
query: id
},
dataType: "json",
type: "GET",
}).done(function(data) { callback(data); });
}
},
createSearchChoice: function (term) {
return {id: term, text: term + ' (new)', title: term };
},
formatResult: FormatContact,
formatSelection: FormatContactSelection,
escapeMarkup: function(m) {
return m;
}
});
});
function FormatContact(contact) {
return contact.text + " (" + contact.title + ")";
}
function FormatContactSelection(contact) {
return " "+ contact.text;
}
function Passvalue() {
var test2 = "Robert"; //just an example, value 'Robert' to be passed on select2 for query
$('#eq').select2("val", [test2]);
}
</script>
My Action Controller:
public ActionResult GetAllEmployees(string query)
{
var db = new Employee().GetAllEmployees(query).
ToList();
return Json(db, JsonRequestBehavior.AllowGet);
}
BL:
public IQueryable<Object> GetAllEmployees(string search)
{
var ctx = new NorthwindEntities();
var dbQuery =
(from i in ctx.Employees
where i.FirstName.Contains(search) || i.LastName.Contains(search)
select new
{
id = i.EmployeeID,
text = i.FirstName + " " + i.LastName,
title = i.Title
});
return dbQuery;
}
Instead of using "val" use "data". Something like this
this.$("#yourSelector").select2("data", [{ id: 1, text: "Some Text" },{ id: 2, text: "Some Other Text" }]);
So something like this would work for you...
var existingData = this.$("#yourSelector").select2("data");
existingData.push({ id: 11, text: "Some Text" });
this.$("#yourSelector").select2("data", existingData);
P.S : I have not tested the above code.

Creating new tags in a Select2 tag textarea

I have an input (textarea) that has Select2's tags applied to it. So when a user types in the name of an item that exists in my data base, it shows a list of matching items and the user can select one and a tag is created.
Here is my code so far for basic tag functionality:
$('#usualSuppliers').select2({
placeholder: "Usual suppliers...",
minimumInputLength: 1,
multiple: true,
id: function(e) {
return e.id + ":" + e.name;
},
ajax: {
url: ROOT + 'Ajax',
dataType: 'json',
type: 'POST',
data: function(term, page) {
return {
call: 'Record->supplierHelper',
q: term,
page_limit: 10
};
},
results: function(data, page) {
return {
results: data.suppliers
};
}
},
formatResult: formatResult,
formatSelection: formatSelection,
initSelection: function(element, callback) {
var data = [];
$(element.val().split(",")).each(function(i) {
var item = this.split(':');
data.push({
id: item[0],
title: item[1]
});
});
//$(element).val('');
callback(data);
}
});
Is there a way for a new tag to be created if the text typed does not exist? Initially I thought this could some how be done by delimiting with spaces, but some items (supplier names) will have spaces in them, so that won't work.
I think when no matches are found the user needs to somehow "create" the tag by pressing a button that could appear in the drop down box, but I have no idea how to do this.
How can I allow users to create new tags that may have spaces in them and still be able to carry on adding more tags, existing or otherwise?
Yes you can do it. There is a example in the documentation. Look at http://ivaynberg.github.io/select2/#events
$("#e11_2").select2({
createSearchChoice: function(term, data) {
if ($(data).filter( function() { return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
},
multiple: true,
data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});
You have to create a function like createSearchChoice, that returns a object with 'id' and 'text'. In other case, if you return undefined the option not will be created.

Categories