45

In previous versions I could do:

$('#search').typeahead({
  name: 'Search',
  remote: '/search?query=%QUERY'
});

But since the 0.10 update, typeahead.js is asking us to define source which I cannot make to work. How do I define remote without having to define a dataset function?

Ben Smith
  • 19,589
  • 6
  • 65
  • 93
Zuhaib Ali
  • 3,344
  • 3
  • 20
  • 32

3 Answers3

104

Typeahead.js version 0.10.0 now uses a separate component called a suggestion engine for providing the suggestion data. The suggestion engine which ships with Typeahead.js is called Bloodhound.

Hence you cannot "define remote without having to define a dataset function".

An example of this working with a remote data source (I'm querying the TheMovieDb API, try searching for "Aliens" for example) can be found here:

http://jsfiddle.net/Fresh/UkB7u/

The code is here:

// Instantiate the Bloodhound suggestion engine
const movies = new Bloodhound({
  datumTokenizer: datum => Bloodhound.tokenizers.whitespace(datum.value),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
    url: 'http://api.themoviedb.org/3/search/movie?query=%QUERY&api_key=f22e6ce68f5e5002e71c20bcba477e7d',
    // Map the remote source JSON array to a JavaScript object array
    filter: movies => $.map(movies.results, movie => ({
      value: movie.original_title
    }))
  }
});

// Initialize the Bloodhound suggestion engine
movies.initialize();

// Instantiate the Typeahead UI
$('.typeahead').typeahead(null, {
  displayKey: 'value',
  source: movies.ttAdapter()
});

Note how the filter function allows you to choose what you want to use as a typeahead suggestion from a non-trivial JSON data source.


Update for Typeahead 0.11.1

For those that are using the newer version of typeahead, a working example based off the original question can be found here:

http://jsfiddle.net/Fresh/bbzt9hcr/

With respect to Typeahead 0.10.0, the new version (0.11.1) has the following differences:

  • The "filter" function has been renamed to "transform".
  • No need to call initialize on the Bloodhound object, nor do we need to call ttAdapter() when assigning it to the remote source.
  • Now need to specify the wildcard (e.g. %QUERY) within the remote options hash.
Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • 17
    This is sad because the functionality `bloodhound` is offering is far more than what I need. It used to be pretty simple until 0.9.3 – Zuhaib Ali Feb 03 '14 at 17:26
  • 1
    The simplest remote example is called "Prefetch Backed by Remote" in "http://twitter.github.io/typeahead.js/examples/". Whilst it is a little more involved, I don't think its too much of an overhead to use. Also many of the remote parameters are the same as before. – Ben Smith Feb 03 '14 at 17:30
  • 7
    The official [documentation](https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#datasets) mentions that we can use custom functions as `source` . I guess that would be simpler, provided that we're able to figure out how. – Zuhaib Ali Feb 03 '14 at 17:43
  • 1
    Yes you can also create a custom source, but I think in the majority of use cases Bloodhound should be good enough. – Ben Smith Feb 03 '14 at 17:51
  • AH well... let me give it a try. – Zuhaib Ali Feb 03 '14 at 17:53
  • Worked... and now I understand why we cannot call remote directly anymore. – Zuhaib Ali Feb 03 '14 at 20:47
  • 8
    I agree with zuhaib, I think Bloodhound jst made typeahead harder and a tad bloated. – Phil Feb 04 '14 at 16:45
  • 17
    The functionality of bloodhound was there in previous versions of typeahead.js, it was just coupled with the jQuery plugin. In v0.10, I've decoupled the two to allow devs who don't need an advanced suggestion engine to define their own data source. As a result, the API isn't as simple – I'm hoping to address this in upcoming releases. – jharding Feb 05 '14 at 09:57
  • 2
    What a load of JUNK for a simple solution, Typeahead is really bloating it down. – Clain Dsilva Mar 11 '15 at 05:51
  • @benSmith I updated your code, But now it does not select properly http://jsfiddle.net/UkB7u/872/ – Sahan Apr 22 '15 at 00:09
  • @user3656084 I like the way you've added to my example :) To include the selected text in the input control you need to set the displaykey to "title". See here http://jsfiddle.net/Fresh/md7bvgam/ – Ben Smith Apr 22 '15 at 00:18
  • 12
    The Bloodhound engine just makes everything super complicated. I just need a working autocomplete, not a Suggestion engine. #OverEngineering. – Robert Reiz Jul 05 '15 at 19:07
  • 1
    What exactly does the `ttAdapter` do? I couldn't find it anywhere! – Alvaro Jul 14 '15 at 14:35
  • @Alvaro ttadapter is used to integrate with a jquery plugin for remote calls. Search for "ttadapter" [here](https://github.com/twitter/typeahead.js/blob/master/src/bloodhound/bloodhound.js) to see the library code. I agree that it's not very intuitive! From looking at the Typeahead [remote example](http://twitter.github.io/typeahead.js/examples/#remote), it looks like its no longer necessary in newer versions of Bloodhound. – Ben Smith Jul 14 '15 at 23:55
  • @BenSmith it doesn't work without it. But as I didn't see it anywhere in the docs I found it very strange. – Alvaro Jul 15 '15 at 09:08
  • 2
    I'm glad I'm in the company of others who think that this is a total overcomplication of what should be relatively simple. I've got a super-duper suggestion remote source - I don't need my client side to try and do the same thing. Oh well, back to jQuery UI Autocomplete it is. – dKen Aug 19 '15 at 19:01
  • @BenSmith Sorry, but your jsfiddle example while very cool is also way too cryptic with no helpful comments (much like the documentation of typeahead). For example I am am trying to configure remote properly, but what is "%Query" and how do I get my query value injected into the url? – TriumphST Sep 23 '15 at 01:36
  • Using the bloodhound is far too complicated and not needed at all (if you have a remote JSON then you would expect that remote service to filter, otherwise you would just use a static JSON clientside, right?) -> http://stackoverflow.com/questions/35451319/typeahead-change-source – davidkonrad Feb 23 '16 at 12:53
  • @ZuhaibAli you're the first person I have heard complain because somebody went an extra mile instead of being lazy I suggest you take time and learn the API. I haven't mastered it all but I am here trying to because I know in the long run knowing more is better than knowing just enough – qualebs Jul 27 '17 at 11:43
  • How would one use a remote url (as in your example) but have the input string update the url? – SumNeuron Apr 12 '18 at 10:33
30

Well you can do something like:

$('input#keywords').typeahead({
    highlight: true,
},
{
  name: 'brands',
  display: 'value',
  source: function(query, syncResults, asyncResults) {
    $.get('/search?q=' + query, function(data) {
      asyncResults(data);
    });
  }
})

source: Using Typeahead.js without Bloodhound

Aqabawe
  • 339
  • 3
  • 7
10

If you want to use ajax POST data instead GET data for more controlled ajax calls, you may use this structure:

var meslekler = new Bloodhound({
    datumTokenizer: function (d) {
            return Bloodhound.tokenizers.whitespace(d.isim);
        },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: 'my_url_with_or_without_%query_token.php',
        ajax:{
            type:"POST",
            cache:false,
            data:{
                limit:5
            },
            beforeSend:function(jqXHR,settings){
                settings.data+="&q="+$('.tt-input').typeahead('val');
            },
            complete:function(jqXHR,textStatus){
            meslekler.clearRemoteCache();
            }
        }
    }
});
meslekler.initialize();
$('.typeahead').typeahead(null, {
    name:'meslekler',
    displayKey: 'isim',
    source: meslekler.ttAdapter()
});
MERT DOĞAN
  • 2,864
  • 26
  • 28