Jason King Team : Web Development Tags : Web Development Tips & Tricks jQuery

Twitter's Typeahead plugin and KnockoutJs

Jason King Team : Web Development Tags : Web Development Tips & Tricks jQuery

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.