1
votes

I'm trying to use Twitter's typeahead.js in a Vue component, but although I have it set up correctly as tested out outside any Vue component, when used within a component, no suggestions appear, and no errors are written to the console. It is simply as if it is not there. This is my typeahead setup code:

         var codes = new Bloodhound({
          datumTokenizer: Bloodhound.tokenizers.obj.whitespace('code'),
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          prefetch: contextPath + "/product/codes"
        });
        $('.typeahead').typeahead({
            hint: true,
            highlight: true,
            minLength: 3
          },
          {
            name: 'codes',
            display: 'code',
            source: codes,
            templates: {
              suggestion: (data)=> {
                return '<div><strong>' + data.code + '</strong> - ' + data.name + '</div>';
              }
            }
          });

I use it with this form input:

<form>
<input id="item" ref="ttinput" autocomplete="off" placeholder="Enter code"     name="item" type="text" class="typeahead"/>
</form>

As mentioned, if I move this to a div outside Vue.js control, and put the Javascript in a document ready block, it works just fine, a properly formatted set of suggestions appears as soon as 3 characters are input in the field. If, however, I put the Javascript in the mounted() for the component (or alternatively in a watch, I've tried both), no typeahead functionality kicks in (i.e., nothing happens after typing in 3 characters), although the Bloodhound prefetch call is made. For the life of me I can't see what the difference is.

Any suggestions as to where to look would be appreciated.

2

2 Answers

0
votes

LATER: I've managed to get it to appear by putting the typeahead initialization code in the updated event (instead of mounted or watch). It must have been some problem with the DOM not being in the right state. I have some formatting issues but at least I can move on now.

0
votes

The correct place to initialize Twitter Typeahead/Bloodhound is in the mounted() hook since thats when the DOM is completely built. (Ref)

Find below the relevant snippet: (Source: https://digitalfortress.tech/js/using-twitter-typeahead-with-vuejs/)

mounted() {

  // configure datasource for the suggestions (i.e. Bloodhound)
  this.suggestions = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    identify: item => item.id,
    remote: {
      url: http://example.com/search + '/%QUERY',
      wildcard: '%QUERY'
    }
  });

  // get the input element and init typeahead on it
  let inputEl = $('.globalSearchInput input');   
  inputEl.typeahead(
    {
      minLength: 1,
      highlight: true,
    },
    {
      name: 'suggestions',
      source: this.suggestions,
      limit: 5,
      display: item => item.title,
      templates: {
        suggestion: data => `<a href="${data.slug}">${data.title}</a>`;
      }
    }
  );
}

You can also find a working example: https://gospelmusic.io/ and a Reference Tutorial to integrate twitter typeahead with your VueJS app.