1

I want to create my own auto-complete component.

Each time I make a change to the input, the suggested results don't appear unless I click somewhere else on the page.

How can I make it so that I see the suggested result while I make changes in the input?

$(document).ready(function() {
  element = document.getElementById('autocomplete-position');
  var top = $('#autocomplete-position').offset().top - $('#position-relative').offset().top;
  var rect = element.getBoundingClientRect();
  var width = element.offsetWidth;
  $('.autocomplete-suggestions').css('top', top).css('left', rect.left).css('width', width);
  $('#q').change(function() {
    $.ajax({
      url: 'http://localhost:3000/search',
      data: {
        term: $('#q').val()
      },
      success: function(data) {
        $('.autocomplete-suggestions').children().remove();
        data.forEach(function(element) {
          $('.autocomplete-suggestions').append(' <div class="autocomplete-suggestion"><p>' + element.name + '</p></div>');
        });
      }
    });
  });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="position-relative"></div>
<input type="text" name="q" id="q" autocomplete="off" />
<div id="autocomplete-position"></div>
<div class="autocomplete-suggestions" style="position: absolute; z-index: 999">
</div>
showdev
  • 28,454
  • 37
  • 55
  • 73
Josh
  • 21
  • 6
  • Do you have a text input field inside the div? Where would you input text? What did you try so far? – Wais Kamal Jul 15 '18 at 10:37
  • Hi! Please take the [tour], have a look around, and read through the [help], in particular [*How do I ask a good question?*](/help/how-to-ask) I'm afraid it's not very clear what you're asking here. A [mcve] would really help, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button; [here's how to do one](https://meta.stackoverflow.com/questions/358992/)). – T.J. Crowder Jul 15 '18 at 10:40
  • @WaisKamal Thanks for your response. I edited the question. – Josh Jul 16 '18 at 03:13

2 Answers2

0

If you want to search as you type, I suggest using an event other than change.

When change is bound to an <input>, "the event is deferred until the element loses focus".
Consider the keyup event, which fires "when the user releases a key on the keyboard".

 $('#searchInput').on('keyup',function(){ ... });

Further Recommendations:

I also recommend "debouncing" the handler, which "limits the rate at which a function can fire".
That way the AJAX won't unnecessarily fire a bunch of times in a row if someone is typing fast.

So something like this:

function handleError(jqXHR, textStatus) {
  alert("Request failed: " + textStatus);
}

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this,
      args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

function searchRequest(term) {
  return $.ajax({
    url: 'http://localhost:3000/search',
    method: 'POST',
    data: {
      term: term
    }
  });
}

function updateSuggestions(data) {

  $suggestions.empty();

  data.forEach(function(element) {
    $('<div>', {
      'class': 'autocomplete-suggestion'
    }).append(
      $('<p>', {
        'text': element.name
      })
    ).appendTo($suggestions);

  });

}

var handleKeyUp = debounce(function() {

  var term = $(this).val();

  searchRequest(term)
    .done(updateSuggestions)
    .fail(handleError);

}, 250);


var $suggestions = $('.autocomplete-suggestions');

$('#searchInput').on('keyup', handleKeyUp);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="searchInput">
<div class="autocomplete-suggestions"></div>

In this demonstration, I'm using the debounce function from David Walsh
(as taken from Underscore.js).

For reference, see:
David Walsh - JavaScript Debounce Function
John Dugan - Demystifying Debounce in JavaScript
StackOverflow - Can someone explain the “debounce” function in Javascript

showdev
  • 28,454
  • 37
  • 55
  • 73
0

Try keydown event:

$('#q').on('keydown',function() { 
    $.ajax({
      url: 'http://localhost:3000/search',
      data: {
        term: $('#q').val()
      },
      success: function(data) {
        $('.autocomplete-suggestions').children().remove();
        data.forEach(function(element) {
          $('.autocomplete-suggestions').append(' <div class="autocomplete-suggestion"><p>' + element.name + '</p></div>');
        });
      }
    });
});
Joe L.
  • 4,433
  • 1
  • 19
  • 14