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

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.

Related

How to get async in jQuery autocomplete

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.

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

Select2 - Pass back additional data via ajax call

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
}
]
}
]

Select2 - create an autocomplete select box from 15k cells array

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.

Categories

Resources