Twitter's Typeahead plugin and KnockoutJs
Twitter has released an excellent autocomplete jQuery plugin called typeahead. It’s fast and very customisable. You can easily provide the user with suggestions from a local array, remote web server or precached data from a remote web server.
If you’re using KnockoutJs in your code, here’s an easy way to integrate typeahead with KnockoutJS.
First download typeahead.js from https://twitter.github.io/typeahead.js/ and include the css mentioned here - http://stackoverflow.com/questions/20198247/twitters-typeahead-js-suggestions-are-not-styled-have-no-border-transparent-b
Add the typeahead settings to your Knockout model:
var viewModel = {
self = this;
self.lookupResultId = ko.observable(''); // this will hold the id of the selected option from typeahead
self.typeaheadOptions = {
name: 'towns', // a name for these options
displayKey: 'name', // json property that holds the text value, see the filter function below
limit: 10, // max results to display to the user
minLength: 0, // min input length from the user
prefetch: {
url: '/api/data/towns', // url which returns the lookup data
ttl: 1, // whether to cache the prefetched data on the client
filter: function (list) {
return $.map(list, function (item) { return { name: item.name, id: item.id }; });
}
},
remote: null
};
}
Next we are going to create a Knockout binding that uses typeahead to offer autocomplete functionality to the user.
ko.bindingHandlers.typeaheadJS = { init: function (element, valueAccessor, allBindingsAccessor) { var el = $(element); var options = ko.utils.unwrapObservable(valueAccessor()); var allBindings = allBindingsAccessor(); var data = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace(options.displayKey), queryTokenizer: Bloodhound.tokenizers.whitespace, limit: options.limit, prefetch: options.prefetch, // pass the options from the model to typeahead remote: options.remote // pass the options from the model to typeahead }); // kicks off the loading/processing of 'local' and 'prefetch' initialize(); el.attr("autocomplete", "off").typeahead(null, { name: options.name, displayKey: options.displayKey, // `ttAdapter` wraps the suggestion engine in an adapter that // is compatible with the typeahead jQuery plugin source: data.ttAdapter() }).on('typeahead:selected', function (obj, datum) { id(datum.id); // set the id observable when a user selects an option from the typeahead list }); } };
Then to apply the binding we can add data-bind="typeaheadJS: typeaheadOptions, id: lookupResultId"
to the element. Now when a user selects an option from the autocomplete list, the id of that option will be stored in the lookupResultId observable.