typeahead, bloodhound : remote works but not prefetch
Asked Answered
L

4

14

I want to use prefetch and I can't have it working ! Here is my code :

function initAutocompletion() {
    $("input[data-autocomplete-prefetch-url]").each(function () {
        var $this = $(this);
    var urlPrefetch = $this.data("autocomplete-prefetch-url");
    var prefetch;

    pref = {
        url: urlPrefetch,
        filter: filter
    };

    var bloodHound = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 10,
        prefetch: pref
    });

    bloodHound.initialize();

    $this
        .typeahead('destroy')
        .typeahead({
            hint: true,
            highlight: true,
            minLength: 1
        },
        {
            displayKey: 'value',
            source: bloodHound.ttAdapter()
        });
    });
 }

function filter(list) {
    return $.map(list, function (v) { return { value: v.toString() }; });
}

It doesn't work.

If I use remote instead of prefetch it works !

    var bloodHound = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 10,
        remote: pref
    });

I can't anderstand.

Can anyone help me ?

Lederhosen answered 9/5, 2014 at 16:13 Comment(0)
L
20

Amazingly it worked this morning ! So it drove me to think it was about cache... And it was ! Adding clearPrefetchCache() before initializing bloodhound did the trick.

       bloodHound.clearPrefetchCache();
       bloodHound.initialize();

I think it didn't show any suggestions because it has cached an empty list.

Lederhosen answered 12/5, 2014 at 8:58 Comment(2)
Official example with prefetch didn't work for me without clearPrefetchCache. Adding clearPrefetchCache before initialize helped. Though it doesn't explain, what's going on.Shammer
Probably worth noting that this may not be a great idea for production depending on your app because if you clear the prefetch cache on every page load, you have to reload the data into the cache on every page load so you only get the advantage of the cache until you switch pages or reload the current page. Probably a great idea for a development environment though.Oates
M
10

It's because typeahead already loaded your data from prefetch url and stored it in localStorage. At the time data is in localStorage, prefetch is not invoked.

Try change cacheKey prefetch option like below and reload the page. Prefetch will invoke because there is no data tied to the new cacheKey in localStorage.

var engine = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  prefetch: {
    url: "stations.json",
    cacheKey: "change here!"
  }
});

You can also check local storage with chrome developer tools.

enter image description here

Try to delete local storage data and reload page. Prefetch will invoke.

To remove localStorage data before Bloodhound initialization makes its prefetch invoke at every initialization time.

localStorage.removeItem("YOUR CACHEKEY");

// Bloodhound initialization with YOUR CACHEKEY.

clearPrefetchCache() before initialize() is better, I think.

Macready answered 14/3, 2015 at 17:18 Comment(4)
.initialize(true) also makes the cache clear each time it's called.Essence
Great info, doesn't provide the solution though.Rossy
@Stuffix I don't think so. In my testing environment, I have .initialize(true). If I remove .clearPrefetchCache() from before the initialize, the prefetches stop hitting my server. From my experiments (version 0.11.1), if you want to clear the prefetch cache, you have to call .clearPrefetchCache() before .initialize(true)Incurrence
@Incurrence you probably right, I wrote this comment 3 years ago so things might have change since. I didn't messed with typeahead since.Essence
I
2

I ran across your question while having issues getting prefetch to work even though remote was working fine. I first worked through caching concerns (since it's been an issue before), but it still wasn't working.

Next I implemented templates in typeahead so I could get some feedback regarding what was happening when I clicked and typed in the field and nothing happened. My notFound template was appearing. This seemed odd since I could see prefetch hit the server. With debug output at the server I could also tell the server was generating the proper json response.

When inspecting the json though I noticed that it had no whitespace and my bloodhound datumTokenizer was configured as Bloodhound.tokenizers.whitespace. This caused me to dig deeper into how the tokenizers are supposed to work.

I found this very helpful: https://github.com/twitter/typeahead.js/blob/master/doc/migration/0.10.0.md#tokenization-methods-must-be-provided

My issue was resolved after switching to:

datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.value);

(where .value is the json property I want to search)

Incurrence answered 20/4, 2017 at 18:41 Comment(1)
Could you please elaborate on tokenizers? We don't understand why they'd differ for prefetch vs remoteTrotman
P
0

Probably, you are trying to prefetch data earlier than urlPrefetch gets a value. Try to dump urlPrefetch to console and check that it has a valid url.

Propagable answered 11/5, 2014 at 3:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.