Use different value from JSON data instead of displayKey using Typeahead
Solution 1
displayKey
is used to indicate which key should be shown in the dropdown list and in the input field after the user has selected an entry.
If you want the entries shown in the dropdown list to be different from what ends up in the input field you need to use a custom template.
From the documentation:
suggestion
– Used to render a single suggestion. If set, this has to be a precompiled template. The associated suggestion object will serve as the context. Defaults to the value ofdisplayKey
wrapped in ap
tag i.e.<p>{{value}}</p>
.
Something like this should work:
$('.typeahead').typeahead(null, {
name: 'stocks',
displayKey: 'company_name',
source: stocks.ttAdapter(),
templates: {
suggestion: function (stock) {
return '<p>' + stock.code + '</p>';
}
}
});
The submitted template will be used to show stock.code
in the dropdown list, while stock.company_name
will be shown in the input field after the user selects an entry.
Solution 2
I am no jQuery / JavaScript-Guru. So I prefer it the easy way. Just to understand what I did when I look at my code later...
Thanks to Eric Saupe I found a smart solution:
//JSON FILE
[
{
"company_name": "Facebook",
"code": "fb",
},
{
"company_name": "Google",
"code": "goog",
},
{
"company_name": "Yahoo",
"code": "yhoo",
},
{
"company_name": "Apple",
"code": "aapl",
},
{
"company_name": "Royal Mail",
"code": "rmg.l",
},
]
// JS SCRIPT
var stocks = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('company_name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: 'javascripts/stockCodes.json'
});
stocks.initialize();
$('.typeahead').typeahead(
null, {
name: 'stocks',
displayKey: 'company_name',
source: stocks.ttAdapter()
}).on('typeahead:selected', function(event, data){
$('.typeahead').val(data.code);
});
Just use the typeahead custom events as described in the docs on github.
Hope, this helps (and when it's just for my own later reference).
Solution 3
You need to use the ´displayKey´ variable. See below copy-paste from the typeahead docs:
displayKey – For a given suggestion object, determines the string representation of it. This will be used when setting the value of the input control after a suggestion is selected. Can be either a key string or a function that transforms a suggestion object into a string. Defaults to
value
.
https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md
Your specific code would then be something like this:
var stocks = new Bloodhound({
datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.code); },
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 3,
prefetch: {
url: 'javascripts/stockCodes.json',
filter: function(list) {
// This should not be required, but I have left it incase you still need some sort of filtering on your server response
return $.map(list, function(stock) { return { code: stock.code, company_name: stock.company_name }; });
}
}
});
stocks.initialize();
$('.typeahead').typeahead(null, {
name: 'stocks',
displayKey: function(stock) {
return stock.company_name;
},
source: stocks.ttAdapter()
});
I had a very similar requirement on my own site, and I had this working with no issue. I have not tried this particular example though, so let me know if it works.
Remember to call stocks.clearPrefetchCache();
to clear your cache to easier track bugs.
Solution 4
If I read correctly, I believe this is what you want:
var stocksData = [{
"Facebook": "fb",
}, {
"Google": "goog",
}, {
"Yahoo": "yhoo",
}, {
"Apple": "aapl",
}, {
"Royal Mail": "rmg.l",
}, ];
var stocks = new Bloodhound({
datumTokenizer: function (d) {
for (var prop in d) {
return Bloodhound.tokenizers.whitespace(d[prop]);
}
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 3,
local: stocksData,
});
stocks.initialize();
$('input').typeahead(null, {
name: 'stocks',
displayKey: function(stocks) {
for (var prop in stocks) {
return prop;
}
},
source: stocks.ttAdapter()
});
You will of course want to change the local to prefetch/remote like you had for the json file.
UPDATE
user1779796
Updated on July 09, 2022Comments
-
user1779796 almost 2 years
I have started using Typeahead.js and am struggling to figure out a way of allowing a user to type and search for a company name, once selected input the associated company code.
.json file:
[{ "company_name": "Facebook", "code": "fb", }, { "company_name": "Google", "code": "goog", }, { "company_name": "Yahoo", "code": "yhoo", }, { "company_name": "Apple", "code": "aapl", }, { "company_name": "Royal Mail", "code": "rmg.l", }]
.js Script:
var stocks = new Bloodhound({ datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.code); }, queryTokenizer: Bloodhound.tokenizers.whitespace, limit: 3, prefetch: { url: 'javascripts/stockCodes.json', filter: function(list) { return $.map(list, function(stock) { return { code: stock }; }); } } }); stocks.initialize(); $('.typeahead').typeahead(null, { name: 'stocks', displayKey: 'code', source: stocks.ttAdapter() });
Currently, this just displays the list of codes when the user types in the input field. However, I would like to know if there is a way to allow them to search on
code
but once selected, the value in the textbox to becompany_name
? Is this even possible using this plugin. Any help will be greatly appreciated.Thanks!
-
user1779796 about 10 yearsthank you for your answer, much appreciated. I have only just gotten around to using the code provided in the fiddle above. I'm not sure if I explained the problem properly but I am trying to figure out how to place the associated value in the input text box as opposed the the key value. For example, typing 'Facebook' should show Facebook in the drop down list however, once selected, the text box value would show 'fb' instead of 'Facebook'. I have tried tweaking the code provided, but haven't managed to the incorporate this functionality yet. Thank you for your help on this.
-
Alok about 9 yearsYou want to also handle 'typeahead:autocompleted'.
-
NLemay almost 8 yearsSeems like the best solution, but the JSFIDDLE doesn't work anymore. When clicking, it is writing the whole company name.
-
Old Geezer about 7 yearsIs it
typeahead:selected
ortypeahead:select
? Official docs say the latter. Either way, I couldn't get the event to fire. I addedalert(data.code);
to your fiddle and it didn't fire too. What should be the right way? -
Tobse about 7 yearsThe JSFIDDLE works as expected for me. I tested with Firefox and Chrome. I cannot tell if it's :selected or :select. It worked for me with :selected Meanwhile I switched over to jQuery Typeahead (runningcoder.org/jquerytypeahead/documentation). It is well documented and feature-rich and the config is more straightforward (imho).
-
Rehmat about 5 yearsEven after using
setTimeout
method like:setTimeout(function() { $('.typeahead').val(data.code); }, 1);
, it was changing the value back when leaving the input box. So, I had to move to @Esseb's template based solution.