The typeahead control relies on list of available options. This can be both preset-data using the Prefetch or local options and/or remote data, fetched on demand from server when user enters characters in the typeahead control.
In both cases the data has to be groomed in format the typeahead control will understand. The minimum requirement is one value field.
More advanced options require specification of unique key, display name, search phrases and optional fields to be available for the item template for each option.
This can sometimes be complicated converstion. The Knockout binding handler solves this however. Since we do not have knocout in this examples we can still make things a little bit easier by using prepared mapping functions for this task.
You can see those functions in the typeaheadHelpers.js file accompanying the Plunker examples 2 and 3.
This example demonstrate simple use of the typeahead - Svakinn fork using JQuery.
Let's say we have a simple list of country data:
var countryList = [
{code: 'IS', name: 'Iceland', localName: 'Ísland'},
{code: 'GB', name: 'Great Britain', localName: ''},
{code: 'US', name: 'USA', localName: ''},
{code: 'AE', name: 'UNITED ARAB EMIRATES', localName: 'دولة الإمارات العربية المتحدة'},
{code: 'IE', name: 'IRELAND', localName: 'Éire'},
{code: 'IL', name: 'ISRAEL', localName: 'מְדִינַת יִשְׂרָאֵל'},
{code: 'IM', name: 'ISLE OF MAN', localName: 'Ellan Vannin'},
{code: 'IQ', name: 'BRITISH INDIAN OCEAN TERRITORY', localName: 'Chagos Islands'},
{code: 'JP', name: 'JAPAN', localName: ''}
];
This example demonstrates very simple hookup of this data to the typeahead control using the local
or prefetch
option.
For now we are only interested in suggesting country name to the control.
We can use the local
option for the suggestions by preparing the local array first with JQuery:
$('#country1').typeahead({
local: $.map(countryList, function (row) { return { value: row.name }; }),
}).on('typeahead:selected typeahead:autocompleted', function (e, data) { $("#selText").text(data.value); });
Then we attach the selected
and autocompleted
event to grab selections and autocompletions into the selText
span.
In case we wanted to do something special while loading the initial data we can also use the prefetch
option as function:
$('#country1').typeahead({
prefetch: function () {
var data = $.map(countryList, function (row) { return { value: row.name }; });
console.log('Got country data with ' + data.length + ' records.');
return data;
},
}).on('typeahead:selected typeahead:autocompleted', function (e, data) { $("#selText").text(data.value); });
See the Plunker JQuery demo here
Now we want to extend the previous example to allow for the following :
1) The suggestions are to be able to look up countries by Code, Name and Local name
2) We want to display the local name and code in the suggestion dropdown
3) Let's throw in country flag icons to make it pretty.
4) We want the list to be pre-initialized on Iceland
5) We will only accept countries that exist in the country list: text must match the selected country name
6) Display country info from the selected country below
You would think that to accomplish all this you need a looooot of code ? Well yes if... we did not have a feature rich typeahead control. We will use helper functions borrowed from the knockout binding handler to help us build the required typeahead datums
To specify the lookup names we pass comma separated parameter to the helper funcion containing the 2 extra columns (besides the name) we want to be able to lookup by:
tokenFields = 'code,localName'
So to create the appropriate datums to bind to the local option of typeahed we do the following:
var datums = typeaheadPreFilter(countryList, 'code,localName', 'localName', 'code', 'name');
See the datumHelper.js for the helper functions.
To accomplish the searchable and display options, the datums generated by the function above to look like this:
{ code: 'IS', name: 'Iceland', localName: 'Ísland', tokens: ['IS','Ísland'], data: {code: 'IS', name: 'Iceland', localName: 'Ísland'} }
Notice the data
property containing the original record. This is the value that will be returned by the selected
and the autocompleted
event handlers.
Then as an option we point the typeahead to the display name nameKey: 'name'
and to the unique value of the row: valueKey: 'code'
Note that we do not need the name added to the tokens. The reason for that is that this fork uses a different search routine (matcher) from the original typeahead that starts matching with the field referenced as the nameKey before it stars the token search.
Add the icons to the site and name them by the code: IS,GB,US,AE,IE,IL,IM,IQ and JP.
Then we want to think about the item template.
Of course we can include the template text directly in the 'template' option: like this:
template: '<p>{{name}} ({{code}})</p>'
However if we want fancy layout with a lot of html code it is rather ugly to put it directly into to the options.
So what would be more appropriate than to include the template layout section in the html as a hidden element. To make sure it is not rendered, i.e. the image element, we put this all into a script element. We then use the JQuery to pick it up for us to put it into the typeahead option.
The template looks like this:
<script id="OurID" type="text/template" class="template">
<div class="row">
<img class="pull-left" style="margin-right: 5px;" src="/Content/country24/{{code}}.png"</img>
<p class="pull-left">{{name}} ({{code}})</p>
<p class="pull-right" style="margin-right: 5px;">{{localName}}</p>
</div>
</script>
And we can get it to a variable like this:
var templ = $('#countryItemTemplate').text();
This example uses the Hogan template engine. We have to include it in the options: engine: Hogan
.
##4) Pre-set selected datum in the typeahead
We use the setDatum
typeahead method to initialize value of the control to speciffic country. Note that this function accepts the original row format.
The typeahead controll will be able to match the values correctly using the information provided with the nameKey
and valueKey
options.
$('#country1').typeahead('setDatum',countryList[0]);
Of course this has to be done below the line where the typeahead control is attached to the input control.
##5) Restrict selection to available data
So in case we only want to accept countries in our list, the typeahead will allow for this using the option restrictInputToDatum
.
restrictInputToDatum: true
##6) Display selected country Since we have no binding support here we will have to make a function to handle the display of selected country:
function displayCountryInfo(country) {
var showFlag = false;
var flagSrc = '';
var dispName = '';
var localName = '';
if (country !== null) {
showFlag = true;
flagSrc = 'https://raw.github.com/Svakinn/typeahead.js/typeaheadSimple/imgages/' + country.code + '.png';
dispName = country.name;
localName = country.localName;
}
$("#dispName").text(dispName);
$("#dispLocalName").text(localName);
$('#dispImg').attr("src", flagSrc);
if (showFlag)
$('#dispImgSpan').show();
else
$('#dispImgSpan').hide();
}
Then we need to attach event handlers to the 3 handlers that notify about data changes in the typeahead control:
typeahead:selected
- when user selects suggeston
typeahead:autocompleted
- when user autocomplets (via tab or arrow key) suggestion
typeahead:noSelect
- when user leaves the input without valid selecton.
As the option restrictInputToDatum
is used, the only case this happens is if you clear all text from the input.
The event hookup looks like this:
$('#country1').on('typeahead:selected typeahead:autocompleted', function (e, data) { displayCountryInfo(data.data); });
$('#country1').on('typeahead:noSelect', function (e, data) { displayCountryInfo(null); });
Finally typeahead hookup looks like this:
$('#country1').typeahead({ nameKey: 'name', valueKey: 'code', engine: Hogan, template: templ, restrictInputToDatum: true, local: datums});
See the Plunker JQuery fancy demo here Example 3, prefetch:
This example shows how to use pefetchHandler
to load prefetched data by our own internal function and thus be in perfect control of the prefetch data.
We can omit the prefetch options and just set the handler function as the prefetch
option like this, if we do not require extra options like ttl or cacheKey.
{ prefetch: handlerSync, valueKey: 'code', nameKey: 'name', template: templ}"
What is new here is the handlerSync prefetch function. If we are handling synchronous fetch, (do not have to wait for remote response) we do not have to wrap the result in promise, just return the data.
function handlerSync() {
var data = typeaheadPreFilter(countryList, 'code,localName', 'localName', 'code', 'name');
return data;
}
The next typeahead control demonstrates asynchronous prefetch.
{minLength: 0, prefetch: handlerAssSync, valueKey: 'code', nameKey: 'name', template: templ}"
Note that this one is configured to show all available options when focused minLength: 0
.
We will be using the prefetch function handlerAssync that will delay execution and return promise.
How to set-up busy indicator to the control is also demonstrated here, using the new typeahead:busyUpdate
event.
The assync handler function looks like this:
function handlerAsSync() {
var data = typeaheadPreFilter(countryList, 'code,localName', 'localName', 'code', 'name');
var def = $.Deferred();
function onTimeout() {
def.resolve(data);
}
setTimeout(onTimeout,3000);
return def;
}
Above we use setTimeout()
to delay the execution so we can see a progress indicator fire off (when the prefetched data is not fetched from the cache).
The hookup looks like this:
$('#country2').on('typeahead:busyUpdate',
function(e,isBusy){
if (isBusy)
$('#busyDiv').show();
else
$('#busyDiv').hide();
});
In the Plunker demo we use two buttons below demonstrate the clearCache
and the refresh
methods of typeahead.
Another new feature of this typeahead version is that you no longer need to initialize pre-set values using the setQuery
method.
While the input control is initializing you can start to type in text and the suggestions will update automatically once the suggestion data is ready.
See the Plunker JQuery demo here
You will also find the equivilent Knockout examples here