Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Twitter Typeahead.js - remove datum upon selection

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.

like image 605
rpmartz Avatar asked Jan 10 '14 12:01

rpmartz


1 Answers

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);
like image 106
likeuntomurphy Avatar answered Oct 19 '22 12:10

likeuntomurphy