I have an autocomplete feature in my application which makes an ajax request to server.
However, once I get data from server, I want to use the look up feature instead of using the service url(to minimize calls to server).
Here is what my js looks like
$('#country').autocomplete({
serviceUrl : './countryCache?',
paramName : 'countryName',
transformResult : function(response) {
return {
// must convert json to javascript object before process
suggestions : $.map($.parseJSON(response), function(item) {
return {
data : item.name
};
})
};
},
showNoSuggestionNotice:true,
onSelect: function (value, data) {
$('#countryId').val(value.data);
}
});
Here is a sample from my ajax call to countryCache - "India, Iceland, Indonesia".
If the user has typed I, the server returns back the result as above.
Now when the user types in n after I, I dont want to make a call to server again.
Can someone help me achieve it.
There is a simple solution for this in the jQuery UI Autocomplete documentation. There you'll find a section titled Remote with caching that shows how to implement what you are looking for.
I adapted the code from that site to this question, and added some comments for clarification:
var cache = {};
$( "#country" ).autocomplete({
source: function( request, response ) {
// If the term is in the cache, use the already existing values (no server call)
var term = request.term;
if ( term in cache ) {
response( cache[ term ] );
return;
}
// Add countryName with the same value as the term (particular to this question)
// If the service reads the parameter "term" instead, this line can be deleted.
request.countryName = request.term;
// Call the server only if the value was not in the cache
$.getJSON( "./countryCache", request, function( data, status, xhr ) {
cache[ term ] = data;
response( data );
});
},
select: function (event, data) {
$('#countryId').val(data.item.value);
}
});
As I didn't know exaclty the format of the JSON, I just used a basic one that for the text "In" returned: ["India","Indonesia","Spain"] (without ids, just a plain array).
If what you are using is the Ajax AutoComplete plugin for jQuery (the code above looks like it, although the question was tagged with jquery-ui-autocomplete), then you don't have to worry about caching, because the plugin does it automatically for you.
From the plugin's documentation:
noCache: Boolean value indicating whether to cache suggestion results. Default false.
As you didn't specify any value for nocache, then it will take the default value that is false, and it will perform caching directly.
I ended up not using this method at all and going with fast, quick searches with a limit of 100. But since I asked, here is how I sent requests using only the first character:
// global variables: models [], result {}
lookup: function(query, done) {
var mdl = $("#autocomplete").val();
if (mdl.length == 0) {
names = [];
result.suggestions = models;
done(result);
return;
} else if (mdl.length != 1) {
result.suggestions = names;
console.log(result);
done(result);
return;
}
var jqHXR = $.ajax({url: "search.php",
data: {"q": mdl},
dataType: "json",
method: "GET" }
)
.done(function(data, status, jqXHR){
models = [];
$.each( data, function( key, val) {
names.push({ value: val.u, data: { category: genders[val.g] } });
});
result.suggestions = names;
done(result);
})
.fail(function (data, status, errorThrown) {
console.log("failed: "+status+"| error: "+errorThrown);
console.log(data);
});
},
A colleague of mine used devbridge and my research seems to verify that there's an attribute for the devbridgeAutocomplete object for minChars and lookupLimit. Maybe there are different instances of devbridgeAutocomplete, but I thought it was worth posting just in case they're similar, though I should assume you would have seen them already :).
Here's the code:
var a = $('#<%= txtFindName.ClientID %>').devbridgeAutocomplete({
minChars: 3,
lookupLimit: 20,
serviceUrl: 'AutoComplete/ADUsers.aspx',
onSelect: function (suggestion) {
$('#<%= txtTo.ClientID %>').val( $('#<%= txtTo.ClientID %>').val() + ',' + suggestion.data);
$('#<%= txtFindName.ClientID %>').val('');
}
});
Related
this is my first question here! New to using Ajax, and have hit an issue that maybe someone could catch what I am doing wrong.
var featuredList;
$.ajax({
url: "myurl",
type: 'GET',
success: function(result){
featuredList = JSON.stringify(result);
alert(result);
$.each( result, function( key, value ) {
alert('not working');
});
},
error: function(){alert('error');}
});
I have gone this path before with no issues, this time around I cannot get inside the loop. The alert(result) is returning my data just fine.
Thanks!
Hi,
Hope this might help you to process JSON data received from AJAX request, try below code:
jQuery.ajax({
url:'myurl',
dataType: "json",
data:{
classId:'C001'
},
type: "GET",
success: function(data) {
for (var j=0; j < data.length; j++) {
//syntax to get value for given key
//data[j].yourKey
var userId = data[j].userId;
var name = data[j].name;
var address = data[j].address;
}
}
});
Thanks,
~Chandan
As per your code try doing this:it should work
var data = JSON.parse(result);//here result should be json encoded data
$.each( data, function( key, value ) {
alert(value);
});
Use jQuery promises, gives you more semantic and readable code
var featuredList;
$.getJSON("myurl", {"optional": "data"})
.done(function(data){
// successful ajax query
$.each( data, function( key, value ) {
// do whatever you want with your iterated data.
});
});
.fail(function(){
// catch errors on ajax query
});
I do it this way
$.getJSON('url',
function(dataList) { // on server side I do the json_encode of the response data
if(dataList !== null) {
$.each(dataList, function(index, objList ) {
// rest of code here
});
}
});
Hope this works for you as well.
function getArray(){
return $.getJSON('url');
}
var gdata = [];
getArray().then(function(json) {
$.each(json, function(key, val) {
gdata[key] = val ;
});
console.log(gdata);
I had the Same Problem It took 2 days to got the solution.
You have to resolve the promise and return the json object to access the value.
You could easily do this using the open source project http://www.jinqJs.com
/* For Async Call */
var result = null;
jinqJs().from('http://.....', function(self){
result = self.select();
});
/* For Sync Call */
var result = jinqJs().from('http://....').select();
You can also use $.Json to get your solution , here is an example
$.getJSON('questions.json', function (data) {
$.each(data,function(index,item){
console.log(item.yourItem); // here you can get your data
}
}
You can use or print Index if you want it. Its show the data index.
Hope it may help you, I am exactly not sure its your requirement or not, But i have tried my best to solve it.
This will work as the result from ajax call is a string.
$.each($.parseJSON(result), function( key, value ) {
alert('This will work');
});
I can't see what the problem with this is.
I'm trying to fetch data on a different server, the url within the collection is correct but returns a 404 error. When trying to fetch the data the error function is triggered and no data is returned. The php script that returns the data works and gives me the output as expected. Can anyone see what's wrong with my code?
Thanks in advance :)
// function within view to fetch data
fetchData: function()
{
console.log('fetchData')
// Assign scope.
var $this = this;
// Set the colletion.
this.collection = new BookmarkCollection();
console.log(this.collection)
// Call server to get data.
this.collection.fetch(
{
cache: false,
success: function(collection, response)
{
console.log(collection)
// If there are no errors.
if (!collection.errors)
{
// Set JSON of collection to global variable.
app.userBookmarks = collection.toJSON();
// $this.loaded=true;
// Call function to render view.
$this.render();
}
// END if.
},
error: function(collection, response)
{
console.log('fetchData error')
console.log(collection)
console.log(response)
}
});
},
// end of function
Model and collection:
BookmarkModel = Backbone.Model.extend(
{
idAttribute: 'lineNavRef'
});
BookmarkCollection = Backbone.Collection.extend(
{
model: BookmarkModel,
//urlRoot: 'data/getBookmarks.php',
urlRoot: 'http://' + app.Domain + ':' + app.serverPort + '/data/getBookmarks.php?fromCrm=true',
url: function()
{
console.log(this.urlRoot)
return this.urlRoot;
},
parse: function (data, xhr)
{
console.log(data)
// Default error status.
this.errors = false;
if (data.responseCode < 1 || data.errorCode < 1)
{
this.errors = true;
}
return data;
}
});
You can make the requests using JSONP (read about here: http://en.wikipedia.org/wiki/JSONP).
To achive it using Backbone, simply do this:
var collection = new MyCollection();
collection.fetch({ dataType: 'jsonp' });
You backend must ready to do this. The server will receive a callback name generated by jQuery, passed on the query string. So the server must respond:
name_of_callback_fuction_generated({ YOUR DATA HERE });
Hope I've helped.
This is a cross domain request - no can do. Will need to use a local script and use curl to access the one on the other domain.
I have a function that makes an AJAX call and returns the data as JSON.
Donor.prototype.GetFriends = function(callback)
{
$.post(apiUrl + "getfriends",
{
"authentication_code" : this.authcode
},
function(response)
{
if (response)
{
callback(response.result);
}
}, "json");
}
Now in my UI I have the following:
var donor = new Donor();
$("#msg-to").autocomplete({source: function()
{
donor.GetFriends(function(response){response.friends.candidates})
}
});
But this is not working...The json is being returned in firebug, but not displaying in the autocomplte field.
result
Object { error_state=0, friends={...}, error_msg=""}
error_msg
""
error_state
0
friends
Object { candidates="[{"follow_id":"3","0":"...","6":"227.jpg"},false]", donors="[{"follow_id":"4","0":"...","6":"224.jpg"},false]"}
candidates
"[{"follow_id":"3","0":"3","user_id":"227","1":"227","following":"222","2":"222","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},{"follow_id":"5","0":"5","user_id":"225","1":"225","following":"222","2":"222","candidate_id":"55","3":"55","firstname":"Test","4":"Test","lastname":"Candidate","5":"Candidate","image":"225.jpg","6":"225.jpg"},{"follow_id":"1","0":"1","user_id":"222","1":"222","following":"226","2":"226","candidate_id":"59","3":"59","firstname":"New","4":"New","lastname":"Candidate","5":"Candidate","image":"226.jpg","6":"226.jpg"},{"follow_id":"6","0":"6","user_id":"222","1":"222","following":"227","2":"227","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},false]"
donors
"[{"follow_id":"4","0":"4","user_id":"224","1":"224","following":"222","2":"222","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},{"follow_id":"2","0":"2","user_id":"222","1":"222","following":"224","2":"224","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},false]"
Also the json that is returned has a candidate_id, firstname, lastname and imageUrl returned, how can I have these displayed in the results, with the friend_id being the value and the others for display?
Thanks in advance...
Couple of things:
You might need to return the array you're creating in order for the autocomplete to use it
You also need to make sure the array of objects has the correct keys for the autocomplete to use
The minimum required keys that need to available for the autocomplete to work correctly are 'label' and 'value'. Other keys can be included, and can be fetched during an event like select or change.
As an example, I might try something like the following. Adjust your GetFriends function to use the request and response callback functions provided by jQuery automatically, and then feed the formatted data that the autocomplete needs back to them:
Donor.prototype.GetFriends = function(request, response){
// this is where you can grab your search term, if need be...
var search_term = request.term;
$.post(
apiUrl + "getfriends",
{"authentication_code" : this.authcode},
function(data)
{
// process your data here into an array that the autocomplete
// will appreciate...
var autocomplete_array = [];
$.each(data.friends.candidates, function(index, candidate)
{
autocomplete_array.push(
{
label: candidate.firstname + " " + candidate.lastname,
value: candidate.user_id,
another_key: candidate.follow_id,
and_another: candidate.image
});
});
// now send the array back to the response parameter...
response(autocomplete_array);
},
"json"
);
};
Then, I'd simplify the autocomplete initializer parameters to include your function:
$("#msg-to").autocomplete({source: donor.GetFriends});
As an additional note, to get to the keys of the items, you could modify your autocomplete field to include the select or change event handlers I mentioned earlier:
$("#msg-to").autocomplete(
{
source: donor.GetFriends
select: function(event, ui){
alert("You selected: " + ui.item.label);
// or...
alert("You selected: " + ui.item.another_key);
}
});
Hope this helps, and that I didn't have a type-o's! :)
The problem is that $.post method works asynchronously. So when autocomplete tries to get data, your function makes POST call and returns empty result. To solve this try adding "async:false" option to .post call or:
Donor.prototype.GetFriends = function(callback) {
$.ajaxSetup({async:false});
$.post(apiUrl + "getfriends",
{
"authentication_code" : this.authcode
},
function(response)
{
if (response)
{
callback(response.result);
}
}, "json");
}
You have to use the setter in the callback (see the 2nd source parameter in my examples) to add the list. If you use arrays to fill the autocomplete, the array needs objects with a label property. If this works you can add the value property too.
1.) If you can update the result of the ajax-result on server-side, change the result to:
friends
Object { candidates=Array { Object { "label": "Helen Hunt" }, ... }, donors=... }
Then your javascript can be:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// set list
setter(response.friends.candidates);
});
}
});
2.) If you can't make changes at the ajax result and candidates is already an array:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// create autocomplete list
var list = response.map(function(element) {
return {
label: element.firstname + ' ' + element.lastname
};
});
// set list
setter(list);
});
}
});
3.) Otherwise (if candidates is a string) [try this first]:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// parse json string
var jsonresult = $.parseJSON(response);
// create autocomplete list
var list = jsonresult.map(function(element) {
return {
label: element.firstname + ' ' + element.lastname
};
});
// set list
setter(list);
});
}
});
I am using jQuery UI autocomplete for a city search on my site. It starts to search after the user has entered 3 characters.
I'm wondering how to change this script to abort the last query if the user continues typing.
function enableCitiesAutocomplete() {
var url = LIST.urls.api_cities_search;
$('#txt_search_city').autocomplete({
source: url,
minLength: 3,
select: function( event, ui ) {
$(this).val( ui.item.value );
$( "#id_city" ).val( ui.item.id );
$(this).closest('form').submit();
}
});
}
I don't know if you can "abort" a completion that has already begun. But you may be able to get what you want by interrupting the render part of the autocomplete. This might work if the autocomplete consists of a query and a render, and the query involves a network transaction.
If there's a query and a render, and the query is just a search through a locally-stored list, then this probably won't work, because the latency is too low.
This SO question describes how to monkey-patch the renderMenu and renderItem fns in the jQuery autocomplete package. I'm thinking you can use the same monkey-patch approach.
You'd need to specify, as the source, a function, not a URL. This SO question describes how. Then, in that function, increment a count variable that says "a search is in process". Then perform the search by doing an "ajax get". Also patch the renderMenu to (a) only render if a single search is in process, and (b) decrement the search count.
It will probably look something like this:
var queriesInProcess = 0;
var ac = $('#txt_search_city').autocomplete({
minLength: 3,
select : .... ,
// The source option can be a function that performs the search,
// and calls a response function with the matched entries.
source: function(req, responseFn) {
var url = baseUrl + req.term;
queriesInProcess++;
$.ajax({
url: url,
//data: data,
success: function(json,xhr) {
queriesInProcess--;
var a = ....retrieve from the json ....
responseFn( a );
},
errpr : function () { queriesInProcess--; },
dataType: 'json'
});
}
});
ac.data( "autocomplete" )._renderMenu = function( ul, items ) {
if (queriesInProcess > 0) return;
var self = this;
$.each( items, function( index, item ) {
self._renderItem( ul, item );
});
};
If you want to get more sophisticated, you can also try to abort the pending ajax request.
This would need to happen in the source function; you'd need to cache/stash the XHR returned from the $.ajax() call, and call abort() when a new one comes through.
I am developing a heavily scripted Web application and am now doing some Error handling. But to do that, I need a way to access the AJAX parameters that were given to jQuery for that specific AJAX Request. I haven't found anything on it at jquery.com so I am asking you folks if you have any idea how to accomplish that.
Here is an example of how I want to do that codewise:
function add_recording(filename) {
updateCounter('addRecording','up');
jQuery.ajax({
url: '/cgi-bin/apps/ajax/Storyboard',
type: 'POST',
dataType: 'json',
data: {
sid: sid,
story: story,
screen_id: screen_id,
mode: 'add_record',
file_name: filename
},
success: function(json) {
updateCounter('addRecording','down');
id = json[0].id;
create_record(id, 1, 1, json);
},
error: function() {
updateCounter('addRecording','error',hereBeData);
}
})
}
hereBeData would be the needed data (like the url, type, dataType and the actual data).
updateCounter is a function which updates the Status Area with new info. It's also the area where the User is notified of an Error and where a Dismiss and Retry Button would be generated, based on the Info that was gathered in hereBeData.
Regardless of calling complete() success() or error() - this will equal the object passed to $.ajax() although the values for URL and data will not always be exactly the same - it will convert paramerters and edit the object around a bit. You can add a custom key to the object to remember your stuff though:
$.ajax({
url: '/',
data: {test:'test'},
// we make a little 'extra copy' here in case we need it later in an event
remember: {url:'/', data:{test:'test'}},
error: function() {
alert(this.remember.data.test + ': error');
},
success: function() {
alert(this.remember.data.test + ': success');
},
complete: function() {
alert(this.remember.data.url + ': complete');
}
});
Of course - since you are setting this data originally from some source - you could rely on the variable scoping to keep it around for you:
$("someelement").click(function() {
var theURL = $(this).attr('href');
var theData = { text: $(this).text(); }
$.ajax({
url: theUrl,
data: theData,
error: function() {
alert('There was an error loading '+theURL);
}
});
// but look out for situations like this:
theURL = 'something else';
});
Check out what parameters you can get in the callback for error.
function (XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info
this; // the options for this ajax request
}
You can use the ajax complete event which passes you the ajaxOptions that were used for the request. The complete fires for both a successful and failed request.
complete : function (event, XMLHttpRequest, ajaxOptions) {
//store ajaxOptions here
//1 way is to use the .data on the body for example
$('body').data('myLastAjaxRequest', ajaxOptions);
}
You can then retireve the options using
var ajaxOptions = $('body').data('myLastAjaxRequest');