1

What is the correct way to limit results of ui.autocomplete when used with map?

I found similar issue with solution which works for simple array here: Limit results in jQuery UI Autocomplete But my array is a bit nested, apart from the fact that the source is external.

I have also tested another solution here to undefined error: jquery autocomplete limit results

Below is what I adapted from the link, but to no success.

My test:

var sourceUrl = '/path/to/products.json';
$("#auto").autocomplete({
        source: function (request, response) {        
          $.getJSON(sourceUrl, {term: request.term}, function (result) {
                response($.map(result.products, function (item) {
                   var myarray = item.product;
                   console.log(myarray); // the returns look expected (Product One, Product Two, etc)
                   var results = $.ui.autocomplete.filter(myarray, request.term);
                   results.slice(0, 10);
                }));                
          });
        }
}); 

products.json:

{"products": [{"label": "Product One", "product": "Product One", "sku": "12345"},    ...

It will be easier to simply output all the products, but they are are just to many/heavy to hold in dropdowns. Thats why I need to limit the result.

Any hint is very much appreciated. Thanks.

Community
  • 1
  • 1
swan
  • 2,509
  • 3
  • 24
  • 40

1 Answers1

4

From the docs, $.map()

The function can return:

  • the translated value, which will be mapped to the resulting array
  • null or undefined, to remove the item
  • an array of values, which will be flattened into the full array

If you want to stick with map you could add a conditional to limit your results.

$.map(result.products, function (item, i) {
    if(i>9){
        return null
    }
}

The important thing to keep clear here is when you are dealing with the entire array and when you are touching just one element. var myarray = item.product; worries me. Why is each result an array? Can you post the JSON response from sourceUrl?

Ideally, sourceUrl returns an array, and $.map is used to transform each element into the desired form. Usually those elements will be objects, not arrays. So inside of the callback you provide to map there should be no talk of arrays or filtering things. That needs to be done outside the loop.

EDIT FOR COMMENTS:

If your source is a static file I would advise only bringing it in once, instead of making the user re-download it every time they type something in the autocomplete field. Something like the following is probably a better idea.

var sourceData;
$.getJSON('/path/to/products.json', function (result) {
    sourceData = $.map(result.products,function(product){
        return product.product;
    });
});

$("#auto").autocomplete({
        source: sourceData
}); 

Of course, at this point you have to ask yourself if there is a particular reason that file is a separate file, or why it isn't a JS include.

Sinetheta
  • 9,189
  • 5
  • 31
  • 52
  • Thanks. It limit the results, but it doesn't filter the results based on term supplied, defeating the purpose of autocomplete suggestion. – swan May 27 '12 at 03:30
  • I'm confused, why would you need to filter the response? That's what "sourceUrl" is for. If the response wasn't dynamic you would just ask for it once instead of every time a search is made. – Sinetheta May 27 '12 at 03:35
  • Maybe just me confused, so sorry. The sourceUrl is static file containing list of products {"products": [{"label": "Product One", "product": "Product One", "sku": "12345"}, ... My failing code returns all the product names. While I want to limit the returned results to 10 and at the same time limit them by terms. – swan May 27 '12 at 03:38
  • and what are you wanting to display in your autocomplete results? If you don't need control over the label itself you can just feed in a simple array of strings. You'll just need to decide which parts of a "product" are important – Sinetheta May 27 '12 at 03:57
  • The autocomplete suggestion should return "product" limited by terms typed. Your code do not do any filtering based on terms. It simply truncates the results to 10. I also add some additional interactions which are not in mycode, like focus: function( event, ui ) {// insert product name on focus to textfield...}, select: function( event, ui ) {// do another thing to sku, label}, but they are irrelevant to my very question on output limits. – swan May 27 '12 at 04:06
  • If you want the simple answer to your question "how do I trim an array using $.map?" then the answer is there, return null. If you would like to discuss what your goals for this page are, in terms of information flow and user experience then I would be happy to move this conversation to a chat. The bottom line is that very rarely should you be doing any filtering on results yourself, that is precisely what `.autocomplete` is supposed to be doing for you. – Sinetheta May 27 '12 at 04:17
  • Thanks. I must be missing some points in my work. Will need to go back to my drawing room, and digest your answers properly, before deciding to pick up your answer. Thanks a lot. – swan May 27 '12 at 04:23