Question

I'm using typeahead.js 0.9.3 and it's working swimmingly. My question is whether it's possible to remove a datum from a dataset upon the "typeahead:selected" event (or any event, for that matter).

I'm fetching the data in the dataset using Typeahead's prefetch option on page load. I know that I could call $('selector').typeahead('destroy') and re-initalize typehead and use a filter in the prefetch object, but it seems rather heavyweight to have to call the data all over again (we're not caching the data in local storage).

I suppose I'm looking for something akin to the filter function to iterate through the array of datums and remove the previously-selected (or all selected) datum. It doesn't look like there's a public function in typeahead to do this, but maybe I missed it.

I've read through typeahead's docs and searched here but haven't found an answer.

EDIT: I solved the immediate problem by switching from prefetch to local and using an AJAX post call to get the data, set it as a global variable and then passed it to typeahead, where I can add/remove items from the global array of data and then destroy/reinitalize typeahead as needed. Far from ideal, but it works.

Was it helpful?

Solution

As you pointed out this is tricky if not impossible to do without massive hacking of the current typeahead version. There are 3 things you need:

  1. Remote as a function option (where you implement your own getter function that accesses your data, filters the query and removes the items you have already selected.
  2. Cache control: The ability to deny typeahead control to use the cache for the last executed suggestion search.
  3. On-demand suggestion search, refresh the suggestion results only when you need it (when you enter the input box and start typing your query).

The next typeahead version (0.10 currently in development) may support the required features.
But... it so happens that my (Svakinn) typeahead fork supports all three conditions you need. Your configuration should supply the getter function, where you select datums from your init data and filter it by query string and already selected options.

remote: yourGetterFunction

Then you need to disable the suggestion cache:

skipCache: true

If you do not want to wait for the next typeahead release, I suggest you try it out:
https://github.com/Svakinn/typeahead.js/tree/typeaheadSimple There are also live live JQuery and Knockout examples available:
https://github.com/Svakinn/typeahead.js/blob/typeaheadSimple/Examples.md

OTHER TIPS

You can achieve this functionality in Typeahead 0.10 on any Bloodhound dataset, whether remote, prefetched or local.

Just track which data has been selected independently of the Bloodhound dataset and do not use Bloodhound#ttAdapater() as your typeahead source. The ttAdapter method is simply a wrapper for Bloodhound#get(query, cb) — so instead of it, call get(query, cb) directly with a custom callback that checks each suggestion against the current selections.

Here’s a JSFiddle — http://jsfiddle.net/likeuntomurphy/tvp9Q/

var selected = [];

var select = function(e, datum, dataset) {
    selected.push(datum.val);
    $("#selected").text(JSON.stringify(selected));
    $("input.typeahead").typeahead("val", "");
}

var filter = function(suggestions) {
    return $.grep(suggestions, function(suggestion) {
        return $.inArray(suggestion.val, selected) === -1;
    });
}

var data = new Bloodhound({
    name: 'animals',
    local: [{ val: 'dog' }, { val: 'pig' }, { val: 'moose' }],
    datumTokenizer: function(d) {
      return Bloodhound.tokenizers.whitespace(d.val);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,

    // custom suggestion filter is applied after Bloodhound
    // limits the set of possible suggestions
    // see comment by Basti below
    limit: Infinity
});

data.initialize();

$('input.typeahead').typeahead(null,
    {
        name: 'animals',
        displayKey: 'val',
     /* don't use
        source: data.ttAdapter(), */
        source: function(query, cb) {
            data.get(query, function(suggestions) {
                cb(filter(suggestions));
            });
        },
        templates: {
            empty: '<div class="empty-message">No matches.</div>'
        }
    }
).bind('typeahead:selected', select);

try this on, it's work for me.

$('#selector').typeahead('setQuery', "");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top