I am having a terrible time using the jQuery autocomplete - the HTTP request isn't happening - there is no data being passed to source at all. There is no output to the console about any errors.
Has anyone got ideas?
For the record - the AJAX URL/CSRF keys etc are set up using $.ajaxSetup() and work fine for all the other $.ajax() calls.
Would appreciate all help. Thanks
$('.select_location_dropdown').autocomplete({
source: function (request, response) {
$.ajax({
data: {
action:'location_management',
sub_ac:'get_location_list',
query: request.term
},
success: function(data) {
var transformed = $.map(data.search_response, function (el) {
return {
label: el.name
};
});
response(transformed);
},
})
},
limit: 4,
onAutocomplete: function(val) {
},
minLength: 1,
});
It seems like you have not added the url for the ajax call. An ajax call normally looks like this:
$.ajax({
url: 'http://example.com',
data: {},
});
I think it might be because of the extra comma at the end of your autocomplete object.
$('.select_location_dropdown').autocomplete({
source: function (request, response) {
$.ajax({
data: {
action:'location_management',
sub_ac:'get_location_list',
query: request.term
},
success: function(data) {
var transformed = $.map(data.search_response, function (el) {
return {
label: el.name
};
});
response(transformed);
},
})
},
limit: 4,
onAutocomplete: function(val) {
},
minLength: 1
});
minLength doesn't need a comma since it's the last key value pair.
For those of you wondering if I ever got this working, the answer is no - not for this particular use case anyway. I am now using the Dev Bridge jQuery Autocomplete plugin for other AC use cases. After a bit of tweaking, I got it working fine.
I was considering implementing my own with an on(function(){}); method, but decided against it.
HOWEVER, for this particular case:
Instead I am using the Google Maps Places Autocomplete API, which is much better suited anyway for what we need, even if we will end up having to pay for it, it is a "needs must" kind of situation.
Below is the implemented code. It worked straight away.
function initAutocomplete() {
try {
autocomplete_from = new google.maps.places.Autocomplete(
(document.getElementById('select_location_from')), {
types: []
}
);
autocomplete_to = new google.maps.places.Autocomplete(
(document.getElementById('select_location_to')), {
types: []
}
);
autocomplete_to.addListener('place_changed', fillInAddress);
autocomplete_from.addListener('place_changed', fillInAddress);
} catch (ex) {}
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place_a = autocomplete_to.getPlace();
var place_b = autocomplete_from.getPlace();
}
Related
I'd like to know a way of how to update the list values of a ExtJs ComboBox. For instance, I have two comboboxs.
One Combobox determine what values the another ComboBox should have. So, after selecting some of those,
I click the drowndown list (combobox) to see the values. But i dont get reflected.
change: function (combofirst, record) {
Ext.Ajax.request({
-- -- --
-- -- --
success: function (response) {
var combosecond = Ext.getCmp('defaultPackageType');
//I am unable to update the combosecond from below snippet.
combosecond.store = Ext.create('Ext.data.Store', {
fields: ['value', 'display'],
data: [
["N", "No"],
["A", "All accounts"]
] //json response
});
},
failure: function (record, action) {}
});
});
In short, how can I change the values of a ComboBox already has with ajax only.
Hope someone can help me
Thanks
I would also agree to the comment, that creating every time a new store and bind it to the combobox is not the optimal solution. I don't know really the reason why this should be done, but nevertheless here is a working example by using bindStore:
https://fiddle.sencha.com/#view/editor&fiddle/3ci0
Ext.create('Ext.form.field.ComboBox', {
// ...
listeners: {
change: {
fn: function (cb) {
Ext.Ajax.request({
url: 'https://jsonplaceholder.typicode.com/albums',
method: 'GET',
timeout: 60000,
success: function (response) {
var jsonResp = response.responseText;
let jsonObj = Ext.JSON.decode(jsonResp, true)
var combo2 = Ext.getCmp('myCombo2');
combo2.bindStore(Ext.create('Ext.data.Store', {
fields: ['id', 'title'],
data: jsonObj
}));
}
});
}
}
}
});
For selection of value 1 the data is loaded from a different url.
But I would think about whether a new proxy call is necessary and whether you can achieve your requirements by using filters or something else.
I am trying to get Semantic UI's Search autocomplete to work. Everything seems to be working, except for the fact that the autocomplete always says no results found.
This is an example search:
This is the case even though the server response seems to work fine.
Here is the server responding with JSON:
Finally, here is my JQuery code:
$(".ui.search").search({
apiSettings: {
url : "/subtopics/search.json?query={query}"
},
fields: {
results : 'subtopics',
title : 'name'
},
minCharacters : 2
})
;
From all the examples I've seen this is the proper way to tell Semantic UI what fields to look at, but it's not working.
Any help with this issue would be greatly appreciated.
It turns out using the onResponse callback included in the Semantic UI documentation (http://semantic-ui.com/behaviors/api.html#response-callbacks) is the solution to this problem.
Here is the code that ended up working:
$(".ui.search").search({
type: 'category',
minCharacters: 3,
apiSettings: {
onResponse: function(serverResponse) {
var
response = {
results: {}
}
;
//translate Server API response to work with search
$.each(serverResponse.subtopics, function(index, subtopic) {
var
topic = subtopic.topic || 'Unknown',
maxResults = 8
;
if(response.results[topic] === undefined) {
response.results[topic] = {
name: topic,
results: []
};
}
//add result to category
response.results[topic].results.push({
title: subtopic.name
});
});
return response;
},
url: "/subtopics/search.json?query={query}"
}
})
;
I want to have a dropdown with a set of values but also allow the user to "select" a new value not listed there.
I see that select2 supports this if you are using it in tags mode, but is there a way to do it without using tags?
The excellent answer provided by #fmpwizard works for Select2 3.5.2 and below, but it will not work in 4.0.0.
Since very early on (but perhaps not as early as this question), Select2 has supported "tagging": where users can add in their own value if you allow them to. This can be enabled through the tags option, and you can play around with an example in the documentation.
$("select").select2({
tags: true
});
By default, this will create an option that has the same text as the search term that they have entered. You can modify the object that is used if you are looking to mark it in a special way, or create the object remotely once it is selected.
$("select").select2({
tags: true,
createTag: function (params) {
return {
id: params.term,
text: params.term,
newOption: true
}
}
});
In addition to serving as an easy to spot flag on the object passed in through the select2:select event, the extra property also allows you to render the option slightly differently in the result. So if you wanted to visually signal the fact that it is a new option by putting "(new)" next to it, you could do something like this.
$("select").select2({
tags: true,
createTag: function (params) {
return {
id: params.term,
text: params.term,
newOption: true
}
},
templateResult: function (data) {
var $result = $("<span></span>");
$result.text(data.text);
if (data.newOption) {
$result.append(" <em>(new)</em>");
}
return $result;
}
});
For version 4+ check this answer below by Kevin Brown
In Select2 3.5.2 and below, you can use something like:
$(selector).select2({
minimumInputLength:1,
"ajax": {
data:function (term, page) {
return { term:term, page:page };
},
dataType:"json",
quietMillis:100,
results: function (data, page) {
return {results: data.results};
},
"url": url
},
id: function(object) {
return object.text;
},
//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
},
});
(taken from an answer on the select2 mailing list, but cannot find the link now)
Just for the sake of keep the code alive, I'm posting #rrauenza Fiddle's code from his comment.
HTML
<input type='hidden' id='tags' style='width:300px'/>
jQuery
$("#tags").select2({
createSearchChoice:function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term)===0;
}).length===0)
{return {id:term, text:term};}
},
multiple: false,
data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});
Since many of these answers don't work in 4.0+, if you are using ajax, you could have the server add the new value as an option. So it would work like this:
User searches for value (which makes ajax request to server)
If value found great, return the option. If not just have the server append that option like this: [{"text":" my NEW option)","id":"0"}]
When the form is submitted just check to see if that option is in the db and if not create it before saving.
There is a better solution I think now
simply set tagging to true on the select options ?
tags: true
from https://select2.org/tagging
Improvent on #fmpwizard answer:
//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
}).length===0) {
return {id:term, text:term};
}
},
//solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined
Thanks for the help guys, I used the code below within Codeigniter I I am using version: 3.5.2 of select2.
var results = [];
var location_url = <?php echo json_encode(site_url('job/location')); ?>;
$('.location_select').select2({
ajax: {
url: location_url,
dataType: 'json',
quietMillis: 100,
data: function (term) {
return {
term: term
};
},
results: function (data) {
results = [];
$.each(data, function(index, item){
results.push({
id: item.location_id,
text: item.location_name
});
});
return {
results: results
};
}
},
//Allow manually entered text in drop down.
createSearchChoice:function(term, results) {
if ($(results).filter( function() {
return term.localeCompare(this.text)===0;
}).length===0) {
return {id:term, text:term + ' [New]'};
}
},
});
I just stumbled upon this from Kevin Brown.
https://stackoverflow.com/a/30019966/112680
All you have to do for v4.0.6 is use tags: true parameter.
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;
In most cases we need to compare values with insensitive register. And this code will return false, which will lead to the creation of duplicate records in the database. Moreover String.prototype.localeCompare () is not supported by browser Safary and this code will not work in this browser;
return this.text.localeCompare(term)===0;
will better replace to
return this.text.toLowerCase() === term.toLowerCase();
Ok, I feel like I'm going crazy here. I'm using the select2 jquery plugin (version 4), and retrieving data via ajax. So you can type in a name, and it will return that contact information. But I also want to return what organization that contact is a part of.
Here is my select2 initialization:
$('#contact_id').select2({
ajax: {
url: 'example.com/contacts/select',
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data) {
return {
results: data
};
},
cache: true
},
minimumInputLength: 3,
maximumSelectionLength: 1
});
And here is the data I'm returning (laravel framework):
foreach($contacts as $con) {
$results[] = [
'id' => $con->contact_id,
'text' => $con->full_name,
'org' => [
'org_id' => $con->organization_id,
'org_name' => $con->org_name
]
];
}
return response()->json($results);
So isn't 'org' supposed to be attached to either the created option or select element by select2? So I could do something like $('#contact_id').select2().find(':selected').data('data').org or $('#contact_id').select2().data('data').org or something like that?
Idealistically, this would look like:
<select>
<option value="43" data-org="{org_id:377, org_name:'Galactic Empire'}">Darth Vader</option>
</select>
I swear I confirmed this worked last week, but now it's completely ignoring that org property. I have confirmed that the json data being returned does include org with the proper org_id and org_name. I haven't been able to dig anything up online, only this snippet of documentation:
The id and text properties are required on each object, and these are the properties that Select2 uses for the internal data objects. Any additional paramters passed in with data objects will be included on the data objects that Select2 exposes.
So can anyone help me with this? I've already wasted a couple hours on this.
EDIT: Since I haven't gotten any responses, my current plan is to use the processResults callback to spawn hidden input fields or JSON blocks that I will reference later in my code. I feel like this is a hacky solution given the situation, but if there's no other way, that's what I'll do. I'd rather that than do another ajax call to get the organization. When I get around to implementing it, I'll post my solution.
Can't comment for now (low reputation).. so... answering to slick:
Including additional data (v4.0):
processResults: function (data) {
data = data.map(function (item) {
return {
id: item.id_field,
text: item.text_field,
otherfield: item.otherfield
};
});
return { results: data };
}
Reading the data:
var data=$('#contact_id').select2('data')[0];
console.log(data.otherfield);
Can't remember what I was doing wrong, but with processResults(data), data contains the full response. In my implementation below, I access this info when an item is selected:
$('#select2-box').select2({
placeholder: 'Search Existing Contacts',
ajax: {
url: '/contacts/typeahead',
dataType: 'json',
delay: 250,
data: function(params){
return {
q: params.term,
type: '',
suggestions: 1
};
},
processResults: function(data, params){
//Send the data back
return {
results: data
};
}
},
minimumInputLength: 2
}).on('select2:select', function(event) {
// This is how I got ahold of the data
var contact = event.params.data;
// contact.suggestions ...
// contact.organization_id ...
});
// Data I was returning
[
{
"id":36167, // ID USED IN SELECT2
"avatar":null,
"organization_id":28037,
"text":"John Cena - WWE", // TEXT SHOWN IN SELECT2
"suggestions":[
{
"id":28037,
"text":"WWE",
"avatar":null
},
{
"id":21509,
"text":"Kurt Angle",
"avatar":null
},
{
"id":126,
"text":"Mark Calaway",
"avatar":null
},
{
"id":129,
"text":"Ricky Steamboat",
"avatar":null
},
{
"id":131,
"text":"Brock Lesnar",
"avatar":null
}
]
}
]
I'm using select2 in order to create styled select boxes with autocomplete. I have 2 choices, load the data from a json file, or create a simple array from that json and use a workaround to populate the select tag. I read through their api examples but obviously I'm missing something. My goal is to create a drop down list with many elements, the problem is that the data is a huge array, which consists of aprox 15k cells. I tried a workaround using this code:
HTML:
<select multiple="multiple" data-placeholder="Select item" id="itemsList">
JS:
var list = $("#itemsList");
var txt = "";
for(var i=0;i<itemsArray.length;i++){
txt =txt+ '<option value='+itemsArray[i]+'>'+itemsArray[i]+'</option>';
}
list.append(txt);
This works, but obviously select2 manages things more efficiently, as this "method" takes several good seconds to load the data in to the DOM.
The second approach is to load the json straight to the select2 box and let the framework to manage the construction, but this leads me to an error: Cannot read property 'slice' of undefined.
JSfiddle here
This is the code:
HTML:
<div class="input-group" id="itemContainer">
<label> Select an item: </label>
<select multiple="multiple" data-placeholder="Items list" id="itemList">
</select>
</div>
JS:
$("select").select2({
ajax: {
//this is a small demo json to illustrate its structure
url: "https://api.myjson.com/bins/5amne",
dataType: 'json',
delay: 0,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
console.log(data);
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
});
Your processData function should handle custom data format, e.g. parse it in a way that is understandable by the select2. Here's how it can be done:
processResults: function (data) {
var results = $.map(data, function (value, key) {
return {
text: key,
children: $.map(value, function (v) {
return {
id: v,
text: v
};
})
};
});
return {
results: results,
};
},
See the updated JSFiddle
Edit
If you want the select2 to handle filtering for you, there are two ways of doing that:
Adding server-side support;
Handling everything on the client.
Since you're loading data via from a static JSON file, you need to go #2. In order to do that, you first need to load all the data, parse it, and only then initialize the select2 control. You can do it like this:
function processData(data) {
return $.map(data, function (value, key) {
return {
text: key,
children: $.map(value, function (v) {
return {
id: key + v,
text: v
};
})
};
});
}
function initSelect2(data) {
$("select").select2({
data: data
});
}
$.ajax({
url: "https://api.myjson.com/bins/1n1rm",
dataType: 'json',
cache: true,
success: function (data) {
initSelect2(processData(data));
}
});
In order to use json for select2, the json format should be something like this:
{ results: [ {id:'first', text:'a'}, {id:'second', text: 'b'} ]
, more: false }
JSON format for jquery-select2 multi with ajax
Your current json doesn't seem to have the right format. I think you should change your json format.