Question

I'm trying to implement jQuery.autocomplete which I use to enter tags (much like here on SO). However, I don't want to show tags that I have already in my list. If I have added foo already I don't want it to show up as a suggestion. The list of tags are fetched from my server. However, I have some issues with altering the ui.content object.

I use the response method found here:

response: (event, ui)->
  # Fetch already added tags
  current = $('input#photo_tag_list').val().split(',')
  # Filter out already added tags from result
  ui.content = ui.content.filter (el) -> $.inArray(el.label, current) == -1

However, the above doesn't work. It still shows all tags. If I inspect ui.content I can see that it looks correct... Is the above async or something?!

The weird thing is that if I do:

ui.content.push({label: "Foo", value:"Bar"})

Foo shows up in the autocomplete list. But if I do this:

ui.content = []

It still shows everything returned. I would expect an empty list.

Why would this be? How do I modify the result list correctly?

Update Got it to work based on Andrew Whitaker's solution.

Was it helpful?

Solution 2

Ok, I got it based on Andrew Whitaker's answer.

Coffescript:

response: (event, ui)->
  current = $('input#photo_tag_list').val().split(',')
  for el, i in ui.content by -1
    if $.inArray(el.label, current) != -1
      ui.content.splice(i, 1)

Works great!

OTHER TIPS

This is happening because of the way JavaScript passes parameters. ui.content is a copy of a reference to an array. You cannot modify that reference and expect the results to be visible outside of the function. This is better explained here.

For a simplified example, check this out:

function modify(item) {
    item.arr = [];
}

var obj = {
    text: 'hi',
    arr: [1,2,3,4]
};

modify(obj);
console.log(obj);

Fiddle: http://jsfiddle.net/9swwA/1/

The log statement will show that obj.arr is still [1, 2, 3, 4]. You essentially have the same problem.


So to get around this you can use splice to remove the items from the array. Unfortunately you're going to have to add a bit more code:

i = ui.content.length - 1

while i >= 0
  currentItem = ui.content[i]
  index = $.inArray(currentItem, current)
  ui.content.splice i, 1  if index is -1
  i--
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top