Twitter Bootstrap Typeahead - Id & Label
Solution 1
There's a great tutorial here that explains how to do this: http://tatiyants.com/how-to-use-json-objects-with-twitter-bootstrap-typeahead/ (read my comment on that page if it hasn't been reflected yet in the main part of the post).
Based on that tutorial, and the JSON you provided, you can do something like this:
$(':input.autocomplete').typeahead({
source: function(query, process) {
objects = [];
map = {};
var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
$.each(data, function(i, object) {
map[object.label] = object;
objects.push(object.label);
});
process(objects);
},
updater: function(item) {
$('hiddenInputElement').val(map[item].id);
return item;
}
});
Solution 2
As of version 0.10.1 of Twitter Typeahead (https://github.com/twitter/typeahead.js), Id / Label is supported natively:
$('input[name=address]').typeahead({
hint: false
}, {
source: function (query, cb) {
$.ajax({
url: '/api/addresses?q=' + encodeURIComponent(query),
dataType: 'json',
cache: false,
type: 'GET',
success: function (response, textStatus, jqXHR) {
cb(response.data);
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
},
name: 'addresses',
displayKey: 'text'
}).on('typeahead:selected', function (e, suggestion, name) {
window.location.href = '/' + suggestion.id;
});
If the example above, I'm passing an array of objects to the source callback (cb). By specifying displayKey: 'text', I'm telling the library to use the 'text' property for the auto-suggest. When the 'typeahead:select' callback is called, the second argument passed in (suggestion) contains the object that was selected.
Solution 3
To clarify what I was saying in my comment. If you wanted multiple type aheads on the same page you need to define each in a function and create a separate map variable for them.
function initFromField() {
var map;
$('#from:input.autocomplete').typeahead({
source: function(query, process) {
map = {};
var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
objects = constructMap(data, map);
process(objects);
},
updater: function(item) {
$('#hidden-from-input').val(map[item].id);
return item;
}
});
}
function initToField() {
var map;
$('#to:input.autocomplete').typeahead({
source: function(query, process) {
objects = [];
map = {};
var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
objects = constructMap(data, map);
process(objects);
},
updater: function(item) {
$('#hidden-to-input').val(map[item].id);
return item;
}
});
}
function constructMap(data, map) {
var objects = [];
$.each(data, function(i, object) {
map[object.label] = object;
objects.push(object.label);
});
return objects;
}
$(function initFields() {
initFromField();
initToField();
});
Note how I scoped the map variable inside the two field initialization functions. This is important, it makes sure the same map variable is not used by both input fields.
Solution 4
I've been struggling with this problem myself, here is the solution I came up with, for data of the type:
[{'id':an_id, 'name':a_name}]
Was:
$("#memberSearch").typeahead({
source: function (query, process) {
var $this = this //get a reference to the typeahead object
return $.get('/getSwimmerListJSON',function(data){
var options = [];
$this["map"] = {}; //replace any existing map attr with an empty object
$.each(data,function (i,val){
options.push(val.name);
$this.map[val.name] = val.id; //keep reference from name -> id
});
return process(options);
});
},
updater: function (item) {
console.log(this.map[item],item); //access it here
}
});
Solution 5
Here is an encapsulated solution. This solution allows you have more than one typeahead on the same page.
This is a modified version of #13279176 Gerbus answer.
$('.make-me-typeahead').typeahead({
source: function (query) {
var self = this;
self.map = {};
var items = [];
var data = [
{"id": 1, "label": "machin"},
{"id": 2, "label": "truc"}
];
$.each(data, function (i, item) {
self.map[item.label] = item;
items.push(item.label)
});
return items;
},
updater: function (item) {
var selectedItem = this.map[item];
this.$element.data('selected', selectedItem);
return item;
}
});
Now when you need get the key of the current selected item you just need do $('.make-me-typeahead').data('selected')
Related videos on Youtube
Pierre de LESPINAY
Web developer at Masao. Fan of Django/python, Symfony/php, Vue/javascript, Docker EPITECH promo 2004.
Updated on July 09, 2022Comments
-
Pierre de LESPINAY almost 2 years
I'm using Bootstrap 2.1.1 and jQuery 1.8.1 and trying to use Typeahead's functionality.
I try to display a label and use an id like a standard
<select />
Here is my typeahead initialization:
$(':input.autocomplete').typeahead({ source: function (query, process) { $('#autocompleteForm .query').val(query); return $.get( $('#autocompleteForm').attr('action') , $('#autocompleteForm').serialize() , function (data) { return process(data); } ); } });
Here is the kind of JSON that I'm sending
[{"id":1,"label":"machin"},{"id":2,"label":"truc"}]
How can I tell
process()
to display my labels and store the selected ID in another hidden field?-
Owlvark over 11 yearsDo any of the comments here help?
-
-
Michael Yagudaev about 11 yearsone important thing to note is the
map
variable there and its scope. According to your code it is global together with theobjects
variable. This mean that you can only have 1 typeahead on the page at a time, otherwise the map object will be shared between typeahead boxes and lead to weird bugs. To have multiple type a heads you will need to use a closure and define the map variable there. -
yayitswei almost 11 years"Names of your objects need to be unique for this to work." So, their solution doesn't work if you're, say, filtering a list of people who might have the same name.
-
Derek Nutile over 10 yearsTwitter Bootstrap has a new path on Github. Try github.com/twbs/bootstrap/pull/3682
-
Marcel Burkhard almost 10 years@yayitswei That would be pointless anyway, as the user wouldn't be able to identify which entry is the right one.
-
yayitswei over 9 years@MarcelBurkhard you could have other elements in the dropdown item to identify the entry, e.g. a facebook picture based on the id.
-
elplatt over 9 yearsI would be interested to see how this can be done if you're using the Bloodhound engine.
-
anweibel about 9 yearsThis plugin worked very well for me with Bootstrap 3: github.com/bassjobsen/Bootstrap-3-Typeahead
-
Mike Castro Demaria about 9 years+1 : you can use the same process if you need more data, like fill many fields with 1 select. Just add more data in the json and in the "updater" duplicate the val() action.
-
Demetris Leptos almost 7 yearsbut what about same display text entries?
-
Demetris Leptos almost 7 yearsin bootstrap-typeahead: displayText function option - finally - no need for maps
-
Vahid Amiri over 6 yearsThis is da answer.
-
makat about 3 yearsdoesn't seem to work with this code - anyone able to get it working?