Dominik H
Dominik H

Reputation: 313

Autocomplete HTML5 input dynamically using datalist & ajax

I try to update a input in a html form via datalist by updating the datalist itself using jquery ajax calls. in case of using ajax the input does not show the options, but when i click into the input field again. the static test version without ajax does work as expected, showing options while typing into the input field.

HTML markup

<form id="formID" class="form-horizontal">
  <div class="control-group">
    <label class="control-label" for="input">Location</label>
    <div class="controls">
      <input type="text" list="LIST_CITIES" id="inputCity" 
      placeholder="Enter your location..">
    </div>
  </div>
  <!-- submit -->
  <button type="submit" class="btn">Submit</button>
</form>

<datalist id="LIST_CITIES"></datalist>

without ajax (does work):

$('.controls').on("input click", "#inputCity", function(e) {
var val = $(this).val();

dataList.empty();

if(val === "" || val.length < 3) return;

if(testObj.results.length) {
  for(var i=0, len=testObj.results.length; i<len; i++) {
    var opt = $("<option></option>").attr("value", testObj.results[i]['city']);
    tempObj[testObj.results[i]['city']] = testObj.results[i]['id'];

    dataList.append(opt);
  }
}

  });

with ajax (does not work while typing):

$('.controls').on("input click", "#inputCity", function(e) {
var val = $(this).val();

dataList.empty();

if(val === "" || val.length < 3) return;

$.ajax({
  type: "GET",
  url: GET_cities,
  data: {startswith: val, maxRows: 5},
  success:function(data){
    if(data.results.length) {
      for(var i=0, len=data.results.length; i<len; i++) {
        var opt = $("<option></option>").attr("value", data.results[i]['city']);
        tempObj[data.results[i]['city']] = data.results[i]['id'];

        dataList.append(opt);
      }
    }
  }
});

Upvotes: 4

Views: 15337

Answers (3)

Steel Brain
Steel Brain

Reputation: 4461

You might want to try out setInterval and clearInterval.

For example:

var wait = false;
$('.controls').on("input click", "#inputCity", function() {
    var val = this.value; // All hail Vanilla JS
    dataList.empty();
    var tempObj = []; // This wasn't in your question, but I had to declare it to get rid of undefined variable errors

    if(val === "" || val.length < 3) return;
    if(wait) window.clearInterval(wait);
    wait = setInterval(function(){
        $.get(GET_cities,{startsWith:val,maxRows: 5},function(result){
            // If what you get is already an array, you can skip this line
            result = JSON.parse(result);
            if(result.results.length){
                for(var city in data.results){
                    if(data.results.hasOwnProperty(city){
                        var opt = $("<option></option>").attr("value",city['city']);
                        tempObj[city['city']] = city['id'];
                        dataList.append(opt);
                    }
                }
            }
        });
    },200); // Change 200 mili-seconds to a delay of your desire
}

Upvotes: 0

Bogdan Le
Bogdan Le

Reputation: 2276

You need to do so:

Remove

var opt = $("<option></option>").attr("value", data.results[i]['city']);

and replace:

dataList.append(opt);

with:

dataList.append("<option value='" + data.results[i]['city'] + "'>");

and add:

$.ajax({
    ...
    async:false,
    ...
});

for me it works!

Upvotes: 0

Saurav Pandit
Saurav Pandit

Reputation: 178

"does not work while typing" --It is because ajax is asynchronous. So when somebody is typing data in input box it is making an ajax call to your server and it will not be able to show output until the response came back. Still you can try async:false in your ajax call. It will lock the browser until your response came back from server but it is not a good idea.

$.ajax({
      type: "GET",
      url: GET_cities,
      **async:false,**
      data: {startswith: val, maxRows: 5},
      success:function(data){
        if(data.results.length) {
          for(var i=0, len=data.results.length; i<len; i++) {
            var opt = $("<option></option>").attr("value", data.results[i]['city']);
            tempObj[data.results[i]['city']] = data.results[i]['id'];

            dataList.append(opt);
          }
        }
      }
    });

Upvotes: 2

Related Questions