Joshi R
Joshi R

Reputation: 164

jquery autocomplete is rendering unfiltered data

I am using jquery auto complete for auto suggestion. The suggestion drop down is showing entire list instead of filtered list.

fiddle - http://jsfiddle.net/joshi101/zn609sdj/7/

HTML

<input type='text' />

jquery

    var json = [{"full_name": "joye dave", "username": "jd"}, {"full_name": "rob", "username": "r"}, {"full_name": "jhon key", "username": "jk"}, {"full_name": "alpacino", "username": "ap"}, {"full_name": "Julia", "username": "Julia"}];
$('input').autocomplete({
    source: function (request, response) {
     response( $.map( json , function(i){
            return{
              id: i.username,
              value: i.full_name
            }
          }))
        },
  focus: function( event, ui ) {
    $( "input" ).val( ui.item.id );
    return false;
  },

});

I have seen similar code working during my search but not getting any clue why this isn't working.

Upvotes: 1

Views: 43

Answers (2)

geoidesic
geoidesic

Reputation: 5053

If you want the results to be alphabetically sorted, then need to sort your object. Autocomplete doesn't do that for you.

https://jsfiddle.net/9zw3fu7t/

E.g.

function compare(a,b) {
  if (a.full_name.toLowerCase() < b.full_name.toLowerCase())
    return -1;
  if (a.full_name.toLowerCase() > b.full_name.toLowerCase())
    return 1;
  return 0;
}

json.sort(compare);

I got the sort function here: Sort array of objects by string property value

To get your example to work though, there are a few gotchas.

Firstly your example isn't actually doing autocomplete – when you type in 'j' for example, it's returning everything containing a 'j' anywhere in the word. I don't think that's what you want. So you need to use regex matching to test against the start of the word.

Secondly, once you do that, your $.map function needs to be moved: https://jsfiddle.net/7ky8whx2/

Here's the full code:

var json = [{"full_name": "joye dave", "username": "jd"}, {"full_name": "rob", "username": "r"}, {"full_name": "jhon key", "username": "jk"}, {"full_name": "alpacino", "username": "ap"}, {"full_name": "Julia", "username": "Julia"}];

var transformJson = function(json) {
  return $.map(json, function(i) {
    return {
      value: i.full_name,
      id: i.username,
    }
  });
}

function compare(a,b) {
  if (a.full_name.toLowerCase() < b.full_name.toLowerCase())
    return -1;
  if (a.full_name.toLowerCase() > b.full_name.toLowerCase())
    return 1;
  return 0;
}

json.sort(compare);

$( "input" ).autocomplete({
  source: function( request, response ) {
    var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( request.term ), "i" );
    response( 
      $.grep( 
        transformJson(json), 
        function( item ){
          found = matcher.test( item.value );
          return found;
        }
      ) 
    );
  }
});

Upvotes: 1

Stock Overflaw
Stock Overflaw

Reputation: 3321

The suggestion drop down is showing entire list instead of sorted list.

What you want here is not sorting, it is filtering.

In your source function, you need to filter which values to use from json. You can also sort, map, etc. here. Something like

response(
  json.filter(
    function (jsonItem) {
      let sanitizedInput = $.ui.autocomplete.escapeRegex(request.term);
      return jsonItem.full_name.match(sanitizedInput);
    }
  )
  .map(/* transform to {id, value} or else in here if need be */)
  .sort(/* sort data in here if need be */)
)

This uses Array.prototype.filter and String.prototype.match. If you want sorting also, check the hint given by geoidesic's answer. Check the behavior of source when passing a function to it for full information.

Upvotes: 0

Related Questions