3

I have an array with some objects that have the same "id" property like this :

var regions = [
  {'id': 1, 'value': 'Ankara'},
  {'id': 2, 'value': 'İstanbul'},
  {'id': 2, 'value': 'Istanbul'}
]

I try to display only the first object of a certain ID if there are duplicate (in this case I want to display 'İstanbul' but not 'Istanbul'). I tried to use a function inside the source property but I failed and I'm not sure to understand where I need to do this ... Here is a snippet :

var regions = [
 {'id': 1, 'value': 'Ankara'},
 {'id': 2, 'value': 'İstanbul'},
 {'id': 2, 'value': 'Istanbul'}
]

$('#myInput').autocomplete({
 source: regions
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<input type="text" placeholder="type here ..." id="myInput">

Any help would be appreciate. Thank you.

Mehdi Brillaud
  • 1,846
  • 2
  • 13
  • 22
  • You need to de-dupe the array of objects before you provide it as the `source` parameter. See this question for details: http://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript – Rory McCrossan Sep 28 '15 at 08:49
  • 1
    Can't you just filter `regions` to exclude the duplicate items? – raina77ow Sep 28 '15 at 08:50
  • I need to keep all items in the array because of special characters. If I remove 'istanbul' from the array and the user type 'ist', 'İstanbul' is not displayed. The backend dev send me the 'raw' version of each region because of this. – Mehdi Brillaud Sep 28 '15 at 08:53
  • In that case you may need to amend the source of autocomplete (or use a different plugin entirely) as I don't believe it supports multiple values per id. – Rory McCrossan Sep 28 '15 at 08:56
  • 1
    Maybe that's what you are looking for: https://jqueryui.com/autocomplete/#folding See example – A. Wolff Sep 28 '15 at 08:56
  • Thank you @A.Wolff . I've already seen this but unfortunately it doesn't solve my problem because of the local (if the system is not turkish, it won't recognize the characters despite the folding). Internationalization is hard :( – Mehdi Brillaud Sep 28 '15 at 08:59
  • But are you using UTF8 encoding? Sounds like then it should work – A. Wolff Sep 28 '15 at 09:02
  • If `folding` is not an option then you can check: http://api.jqueryui.com/autocomplete/#method-_renderMenu . But in this case you will have to handle each and every case manually. – vijayP Sep 28 '15 at 09:03
  • Just to add a demo, this how you should use it i guess: http://jsfiddle.net/vqyr41g2/ – A. Wolff Sep 28 '15 at 09:28
  • Thank you very much @A.Wolff – Mehdi Brillaud Sep 28 '15 at 12:33

2 Answers2

0

This may be your solution. I created one function what will remove duplicates from array based on property. Function will add unique object to uniqueArray, all next items with same id are ignored.

After that I passed uniqueArray to jQuery autocomplete.

Keep in mind Array.reduce works on IE9+

Feel free to ask if you have any questions.

var regions = [
 {'id': 1, 'value': 'Ankara'},
 {'id': 2, 'value': 'İstanbul'},
 {'id': 2, 'value': 'Istanbul'}
]

var uniqueRegions = removeDuplicates(regions, 'id')

function removeDuplicates(arr, field) {
    var u = [];
    arr.reduce(function (a, b) {
        if (a[field] !== b[field]) {
            u.push(b);
        }
        return b;
    }, []);
    return u;
}

$('#myInput').autocomplete({
 source: uniqueRegions
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<input type="text" placeholder="type here ..." id="myInput">
Wlada
  • 1,052
  • 14
  • 25
  • Thank you very much, but as I said in the comment, I need to pass all the items into the plugin and show only on item for each ID. However someone gave me a hint and I managed to achieve what I tried to do, so I'll write an answer. Thanks again ;) – Mehdi Brillaud Sep 29 '15 at 08:07
0

Thanks to vijayP in the comments, I managed to achieve what I tried to do with _renderItem.

Firstly, you need to store in a variable like this :

var autoComplete = $('#myInput').autocomplete({});

Then you can use _renderItem on it, so you can customize the list generated by the plugin :

autoComplete.autocomplete( "instance" )._renderItem = function( ul, item ) {
    //Do your stuff
}

Now you can do what you need in the open event.

Here is a full snippet :

var regions = [{
  'id': 1,
  'value': 'Ankara'
}, {
  'id': 2,
  'value': 'İstanbul'
}, {
  'id': 2,
  'value': 'Istanbul'
}]

var autoComplete = $('#myInput').autocomplete({
  source: regions,
  open: function(event, ui) {
    var $ul = $('#regions');
    $ul.find('li').each(function(id, region) {
      var dataID = $(region).attr('data-id');
      var items = $ul.find('[data-id="' + dataID + '"]');
      console.log($(items).length);
      if ($(items).length > 1) {
        $(items).hide();
        $(items).first().show();
      }
    });
  },
  messages: {
    noResults: '',
    results: function() {}
  }
})
autoComplete.autocomplete("instance")._renderItem = function(ul, item) {
  var $ul = $(ul).prop('id', 'regions')
  return $('<li data-id="' + item.id + '">')
    .append(item.value)
    .appendTo($ul);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<input type="text" placeholder="type here ..." id="myInput">
Mehdi Brillaud
  • 1,846
  • 2
  • 13
  • 22