Carl Weis
Carl Weis

Reputation: 7062

How to format jquery ui autocomplete with function that returns json?

I have a function that makes an AJAX call and returns the data as JSON.

Donor.prototype.GetFriends = function(callback)
{
    $.post(apiUrl + "getfriends",
    {   
        "authentication_code" : this.authcode        
    },
    function(response)
    {
        if (response)
        {
            callback(response.result);
        }        
    }, "json");
}

Now in my UI I have the following:

var donor = new Donor();
$("#msg-to").autocomplete({source: function()
   {
      donor.GetFriends(function(response){response.friends.candidates})
   }
});

But this is not working...The json is being returned in firebug, but not displaying in the autocomplte field.

result
    Object { error_state=0, friends={...}, error_msg=""}

error_msg
    ""

error_state
    0

friends
    Object { candidates="[{"follow_id":"3","0":"...","6":"227.jpg"},false]", donors="[{"follow_id":"4","0":"...","6":"224.jpg"},false]"}

candidates
    "[{"follow_id":"3","0":"3","user_id":"227","1":"227","following":"222","2":"222","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},{"follow_id":"5","0":"5","user_id":"225","1":"225","following":"222","2":"222","candidate_id":"55","3":"55","firstname":"Test","4":"Test","lastname":"Candidate","5":"Candidate","image":"225.jpg","6":"225.jpg"},{"follow_id":"1","0":"1","user_id":"222","1":"222","following":"226","2":"226","candidate_id":"59","3":"59","firstname":"New","4":"New","lastname":"Candidate","5":"Candidate","image":"226.jpg","6":"226.jpg"},{"follow_id":"6","0":"6","user_id":"222","1":"222","following":"227","2":"227","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},false]"

donors
    "[{"follow_id":"4","0":"4","user_id":"224","1":"224","following":"222","2":"222","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},{"follow_id":"2","0":"2","user_id":"222","1":"222","following":"224","2":"224","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},false]"

Also the json that is returned has a candidate_id, firstname, lastname and imageUrl returned, how can I have these displayed in the results, with the friend_id being the value and the others for display?

Thanks in advance...

Upvotes: 0

Views: 702

Answers (3)

scessor
scessor

Reputation: 16115

You have to use the setter in the callback (see the 2nd source parameter in my examples) to add the list. If you use arrays to fill the autocomplete, the array needs objects with a label property. If this works you can add the value property too.

1.) If you can update the result of the ajax-result on server-side, change the result to:

friends
    Object { candidates=Array { Object { "label": "Helen Hunt" }, ... }, donors=... }

Then your javascript can be:

var donor = new Donor();
$("#msg-to").autocomplete({
    source: function(request, setter) {
        donor.GetFriends(function(response) {
            // set list
            setter(response.friends.candidates);
        });
    }
});

2.) If you can't make changes at the ajax result and candidates is already an array:

var donor = new Donor();
$("#msg-to").autocomplete({
    source: function(request, setter) {
        donor.GetFriends(function(response) {
            // create autocomplete list
            var list = response.map(function(element) {
                return {
                    label: element.firstname + ' ' + element.lastname
                };
            });
            // set list
            setter(list);
        });
    }
});

3.) Otherwise (if candidates is a string) [try this first]:

var donor = new Donor();
$("#msg-to").autocomplete({
    source: function(request, setter) {
        donor.GetFriends(function(response) {
            // parse json string
            var jsonresult = $.parseJSON(response);
            // create autocomplete list
            var list = jsonresult.map(function(element) {
                return {
                    label: element.firstname + ' ' + element.lastname
                };
            });
            // set list
            setter(list);
        });
    }
});

Upvotes: 0

Chris Kempen
Chris Kempen

Reputation: 9661

Couple of things:

  • You might need to return the array you're creating in order for the autocomplete to use it
  • You also need to make sure the array of objects has the correct keys for the autocomplete to use

The minimum required keys that need to available for the autocomplete to work correctly are 'label' and 'value'. Other keys can be included, and can be fetched during an event like select or change.

As an example, I might try something like the following. Adjust your GetFriends function to use the request and response callback functions provided by jQuery automatically, and then feed the formatted data that the autocomplete needs back to them:

Donor.prototype.GetFriends = function(request, response){

    // this is where you can grab your search term, if need be...
    var search_term = request.term;

    $.post(
        apiUrl + "getfriends",
        {"authentication_code" : this.authcode},
        function(data)
        {
            // process your data here into an array that the autocomplete
            // will appreciate...
            var autocomplete_array = [];
            $.each(data.friends.candidates, function(index, candidate)
            {
                autocomplete_array.push(
                {
                    label: candidate.firstname + " " + candidate.lastname,
                    value: candidate.user_id,
                    another_key: candidate.follow_id,
                    and_another: candidate.image
                });
            });

            // now send the array back to the response parameter...
            response(autocomplete_array);
        },
        "json"
    );
};

Then, I'd simplify the autocomplete initializer parameters to include your function:

$("#msg-to").autocomplete({source: donor.GetFriends});

As an additional note, to get to the keys of the items, you could modify your autocomplete field to include the select or change event handlers I mentioned earlier:

$("#msg-to").autocomplete(
{
    source: donor.GetFriends
    select: function(event, ui){
        alert("You selected: " + ui.item.label);
        // or...
        alert("You selected: " + ui.item.another_key);
    }
});

Hope this helps, and that I didn't have a type-o's! :)

Upvotes: 1

Vaidas
Vaidas

Reputation: 11

The problem is that $.post method works asynchronously. So when autocomplete tries to get data, your function makes POST call and returns empty result. To solve this try adding "async:false" option to .post call or:

Donor.prototype.GetFriends = function(callback) {
  $.ajaxSetup({async:false});
  $.post(apiUrl + "getfriends",
  {   
    "authentication_code" : this.authcode        
  },
  function(response)
  {
    if (response)
    {
        callback(response.result);
    }        
  }, "json");
}​

Upvotes: 0

Related Questions