How to get async in jQuery autocomplete - javascript

I am using the jQuery autocomplete plugin. The situation is that the hint data is taken via the GET API method. I can't make the code wait until the end of accepting data from the API.
$('#vehicleBrand').autocomplete({
source: function(request, response) {
$('#vehicleBrandValue').val('');
$.get('api/brands', {
query: request.term,
category: $('select[name="vehicleType"]').val()
}, function(data) {
response(data)
})
},
select: function(event, ui) {
$('#vehicleBrandValue').val(ui.item.data);
event.target.classList.remove('border-danger');
prepareModels(ui.item.data);
},
close: function(event, ui) {
if (!$('#vehicleBrandValue').val()) {
alertify.error('Error text here!');
event.target.value = '';
event.target.classList.add('border-danger');
event.target.focus();
}
}
});
In the code above, on the source key, I call the get method to get the data.
let brand = data.car_brand;
$('#vehicleBrand').data("ui-autocomplete").search(brand)
$("#vehicleBrand").data("ui-autocomplete").menu.element[0].firstChild.click()
In the code above I am looking for a car brand and click on it through the script. But the click occurs before the request for data on the source key has time to complete, and the click occurs in the undefined list.
Where can I make the click wait for a response from the function by the key source ?
I tried to use Promise and async/await in function by key source, but it didn't work

Might advise the following:
$('#vehicleBrand').autocomplete({
source: function(request, response){
$.getJSON('api/brands', {
query: request.term,
category: $('select[name="vehicleType"]').val()
}, function(data){
response(data);
});
},
select: function(event, ui) {
$('#vehicleBrandValue').val(ui.item.value);
$(this).removeClass('border-danger');
prepareModels(ui.item.label);
},
close: function(event, ui) {
if (!$('#vehicleBrandValue').val()) {
alertify.error('Error text here!');
$(this).val("").addClass('border-danger').focus();
}
}
});
Need to also make sure that you have { label, value } pair someplace in your data results.
See more: https://api.jqueryui.com/autocomplete/#option-source
Using $.getJSON() is short hand for a AJAX GET Request that is expecting JSON data as a result.
If you are later using this code:
let brand = data.car_brand;
$('#vehicleBrand').data("ui-autocomplete").search(brand)
$("#vehicleBrand").data("ui-autocomplete").menu.element[0].firstChild.click()
The code will execute right away, before results have loaded. You may need to delay the trigger using setTimeout since there is not a Promise to execute after. Something like this might work:
$('#vehicleBrand').autocomplete("search", data.car_brand);
setTimeout(function(){
$("#vehicleBrand").autocomplete("widget").find(".ui-menu-item:eq(0)").trigger("click");
}, 1200);
This give Autocomplete time to load the events before triggering a click event.

Related

ExtJs 4.1.2 ComboBox Update or Reload Based on another ComboBox

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.

JQuery Ajax Autocomplete Not Displaying Result

I have a form that load Jquery autocomplete, I got the result, but it does not shows up (blank with border). Just like this image:
Here's my JQuery Code:
<script type="text/javascript">
// Customer
$('input[name=\'customer\']').autocomplete({
delay: 500,
source: function (request, response) {
$.ajax({
url: 'getCustomer.php?filter_name=' + encodeURIComponent(request.term),
dataType: 'json',
success: function (json) {
response($.map(json, function (item) {
return {
label: item.c_name,
value: item.c_id
}
}));
}
});
},
select: function (event, ui) {
$('input[name=\'customer\']').val(ui.item.label);
$('input[name=\'customer_id\']').val(ui.item.value);
return false;
},
focus: function (event, ui) {
return false;
}
});
</script>
And here's AJAX result:
Anyone here have same problem before? I'm using Admin LTE template by the way. And still wondering what's wrong with my code. I have tried import other Jquery-min-js but still not working. Still displayed like that (blank bordered). FYI: there's no error at console log.
I am guessing that the AJAX response you've shown (as an image) is the actual response from the server, before your $.map() has modified it.
Your $.map() function iterates over that json response from the server, and it tries to use the c_name and c_id property names in each element. But the json from the server does not include those property names - it has customer_id and name.
So the $.map() creates a bunch of empty elements, and passes them on to autocomplete. Autocomplete then has a set of elements to display, but without any labels, which is why you see the dropdown with empty horizontal lines, rather than just nothing at all, which is what you'd see when there's no response/match at all.
You simply need to use the same property names you have in your AJAX:
response($.map(json, function (item) {
return {
label: item.name,
value: item.customer_id
}
}));

jQuery autocomplete not sending data to AJAX

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();
}

$$Hashkey missing when trying to add object with push from autocomplete

Array with hardcoded object shows up in my ng-repeat.
$scope.deltagarelist = [{ label: "Nils", value: "3" }];
This is my javascript/angular hybrid code to get selected values from the autocomplete and push it into my objectarray.
$(".addDeltagare").autocomplete(
{
source: function (request, response) {
$.ajax({
url: url,
data: { query: request.term },
datatype: 'jsonp',
success: function (data) {
response($.map(data, function (item) {
return {
label: item.Label,
value: item.Value
}
}));
}
});
},
minLength: 3,
select: function (event, ui) {
event.preventDefault();
addtolist(ui.item);
console.log($scope.deltagarelist);
$(this).val('');
},
focus: function (event, ui) {
$("#addDeltagare").val(ui.item.label);
return false;
}
});
And my function to push the object into my list.
function addtolist(item) {
$scope.deltagarelist.push({label:item.label,value:item.value});
}
My problem is that my hardcoded guy "Nils" gets a $$hashkey but when I add an object to the list in this way it doesnt get a hashkey and it adds to the array but doesnt show up in my repeat.
Any ideas on how I can change this code to make it work?
Or should I look for other autcompletes thats more "the angular way" ?
The solution is adding a track by to your ng-repeat so that AngularJS doesn't need to use the $$hashkey to track changes.
<div ng-repeat="val in deltagarelist track by val.value">
The $ajax is asynchronous, this means the NG-app is already been build before the data is downloaded. A workaround is to make $ajax sync sothat everything waits until the data is downloaded.

Load data into a Backbone collection from JSON file?

I'm trying to load some data into a Backbone Collection from a local JSON file, using this very basic code:
window.Student = Backbone.Model.extend({
});
window.Students = Backbone.Collection.extend({
model: Student,
});
window.AllStudents = new Students();
AllStudents.fetch({ url: "/init.json"});
console.log('AllStudents', AllStudents);
In the console statement, AllStudents is empty. But init.json is definitely being loaded. It looks like this:
[
{ text: "Amy", grade: 5 },
{ text: "Angeline", grade: 26 },
{ text: "Anna", grade: 55 }
]
What am I doing wrong?
UPDATE: I've also tried adding a reset listener above the .fetch() call, but that's not firing either:
AllStudents.bind("reset", function() {
alert('hello world');
});
AllStudents.fetch({ url: "/init.json"});
No alert appears.
UPDATE 2: Trying this script (reproduced here in full):
$(function(){
window.Student = Backbone.Model.extend({
});
window.Students = Backbone.Collection.extend({
model: Student,
});
window.AllStudents = new Students();
AllStudents.url = "/init.json";
AllStudents.bind('reset', function() {
console.log('hello world');
});
AllStudents.fetch();
AllStudents.fetch({ url: "/init.json", success: function() {
console.log(AllStudents);
}});
AllStudents.fetch({ url: "/init.json" }).complete(function() {
console.log(AllStudents);
});
});
Only one console statement even appears, in the third fetch() call, and it's an empty object.
I'm now absolutely baffled. What am I doing wrong?
The JSON file is being served as application/json, so it's nothing to do with that.
The attribute names and non-numeric attribute values in your JSON file must be double quoted (" ") . Single quotes or no-quotes produces errors and response object is not created that could be used to create the models and populate the collection.
So. If you change the json file content to :
[
{ "text": "Amy", grade: 5 },
{ "text": "Angeline", grade: 26 },
{ "text": "Anna", grade: 55 }
]
you should see the non-empty collection object.
You can change your code to see both success and failure as below:
AllStudents.fetch({
url: "/init.json",
success: function() {
console.log("JSON file load was successful", AllStudents);
},
error: function(){
console.log('There was some error in loading and processing the JSON file');
}
});
For more details, probably it will be a good idea to look in to the way ajax response objects are created.
I/O operations in javascript are almost always asynchronous, and so it is with Backbone as well. That means that just because AllStudents.fetch has returned, it hasn't fetched the data yet. So when you hit your console.log statement, the resources has not yet been fetched. You should pass a callback to fetch:
AllStudents.fetch({ url: "/init.json", success: function() {
console.log(AllStudents);
}});
Or optionally, use the new promise feature in jQuery (fetch will return a promise):
AllStudents.fetch({ url: "/init.json" }).complete(function() {
console.log(AllStudents);
});
fetch() returns a 'success' notification as already stated, but that just means that the server request was successful. fetch() brought back some JSON, but it still needs to stuff it into the collection.
The collection fires a 'reset' event when it's contents have been updated. That is when the collection is ready to use...
AllStudents.bind('reset', function () { alert('AllStudents bind event fired.'); });
It looks like you had this in your first update. The only thing I did differently was to put fetch() in front of the event binding.
I think you need to add {add:true} to the options of fetch,
if you assigned the fetch to a variable, you would get the result as well,
but then its not inside the collection you wanted

Categories

Resources