I am having a lot of trouble getting bootstraps typeahead to work properly with an AJAX source.
If I alert out the array that is being returned it is perfectly fine, even when I hard code it to test it. It seems to return nothing most of the time or only a few items from the array when you have typed in a near match.
Here is what I have at the moment:
$('#companyNameInput').typeahead({
source: function(query, process){
$.ajax({
url: ROOT+'Record/checkCompanyName',
async: false,
data: 'q='+query,
type: 'POST',
cache: false,
success: function(data)
{
companiesFinal = [];
map = {};
companies = $.parseJSON(data);
$.each(companies, function(i, v){
map[v.name] = v.id;
companiesFinal.push(v.name);
})
}
})
process(companiesFinal);
// return ['test1', 'test2'] This works fine
return companiesFinal;
}
Does anyone have an idea why this is working properly?
Here is an example of the object array returned from my PHP script. Objects with IDs 1 and 1216 show up on the typeahead dropdown, but non of the others do. I can not see any patterns or clue as to why only these would show and not the others.
[
{
"id": "1265",
"score": "40",
"name": "LMV AB"
},
{
"id": "10834",
"score": "33",
"name": "Letona"
},
{
"id": "19401",
"score": "33",
"name": "Lewmar"
},
{
"id": "7158",
"score": "33",
"name": "Lazersan"
},
{
"id": "3364",
"score": "33",
"name": "Linpac"
},
{
"id": "1216",
"score": "33",
"name": "L H Evans Limted"
},
{
"id": "1",
"score": "33",
"name": "LH Evans Ltd"
},
{
"id": "7157",
"score": "33",
"name": "Lazersan"
}
]
And finally the array that is past in process(companiesFinal)
:
["LMV AB", "Letona", "Lewmar", "Lazersan", "Linpac", "L H Evans Limted", "LH Evans Ltd", "Lazersan"]
Anyone have any clue? I am still totally clueless as to why this isn't working still 🙁
$('#companyNameInput').typeahead({
source: function(query, process){
companyTOut = setTimeout(function(){
return $.ajax({
url: ROOT+'Record/checkCompanyName',
data: 'q='+query,
type: 'POST',
dataType: 'json',
cache: false,
success: function(data)
{
var count = 0;
var companiesFinal = [];
map = [];
$.each(data, function(i, v){
map[v.name] = [v.id, v.score];
companiesFinal.push(v.name);
})
process(companiesFinal);
}
})
}, 250)
},
minLength: 2,
highlighter: function(item)
{
$('#companyNameInput').closest('.control-group').removeClass('success')
companyLocked = false;
return '<span class="unselectable" title="'+map[item].score+'">'+item+'</span>';
},
updater: function(item)
{
selectedEntityId = map[item][0];
selectedCountryScore = map[item][1];
lockCompany(selectedEntityId);
return item;
}
});
$output .= '['.$output;
foreach($results as $result) {
$output .= '{"id":"'.$result['id'].'",';
$output .= '"score":"'.$result['score'].'",';
$output .= '"name":'.json_encode($result['name']).'},';
}
header('Content-Type: application/json');
echo substr($output, 0, strlen($output)-1).']';
Console output for "parm":
[Object, Object, Object, Object, Object, Object]
0: Object
id: "25024"
name: "part"
score: "75"
__proto__: Object
1: Object
id: "15693"
name: "pari"
score: "75"
__proto__: Object
2: Object
id: "28079"
name: "Pato"
score: "50"
__proto__: Object
3: Object
id: "18001"
name: "PASS"
score: "50"
__proto__: Object
4: Object
id: "15095"
name: "PSR"
score: "33"
__proto__: Object
5: Object
id: "22662"
name: "PRP"
score: "33"
__proto__: Object
length: 6
__proto__: Array[0]
Best Answer
Update 2
Ah, your service returns items that actually don't match the query
parm
. Your typeahead query is'parm'
, with which none of the returned results match. You can override thematcher
function used by the typeahead plugin, see the docs. Simply implement it asreturn true
to match all results returned by your service.Update 1
This is an updated version, that maps the name to an id, which can be used later. A jsfiddle is available.
Original answer
You need to make the call async and call the
process
callback from within the success callback like this:The
return ['test1', 'test2'];
works, because the source function is then basically set to:Notes
There is a one-liner to fill
companiesData
:And you probably want to declare your variables using
var
; otherwise they'll have global scope, which will bite you.