How to return a Json label/value pair from C# Controller Action for jQuery AutoComplete
Asked Answered
E

2

7

I need to create a jQuery Autocomplete textbox that gets a list of names from the DB, and when selected, sends the user to the appropriate page link.

I'm trying to do something just like this post: Fire a controller action from a jQuery Autocomplete selection

The solution makes sense, and the click and redirect works, but I don't know how to return more than just a string list of names.

Current controller code (snippet):

        List<string> Names = new List<string>();
        foreach (Child c in listfromDB)
        {
            Names.Add(c.Name);
            //childNames.Add(new KeyValuePair<string, int>(c.Name, c.ID));
        }
        return Json(Names);

The KeyValuePair didn't seem to work. How do I create an object array instead?

My jQuery code:

$(document).ready(function () {
$("#find-child-box").autocomplete({
source: function (request, response) {
    // define a function to call your Action (assuming UserController)
    $.ajax({
        url: '/Admin/AutoCompleteMyChildren', type: "POST", dataType: "json",

        // query will be the param used by your action method
        data: { query: request.term },
        success: function (data) {
            response($.map(data, function (item) {
                return { label: item, value: item };
            }))
        }
    })
},
minLength: 1, // require at least one character from the user
select: function(event, ui) {
alert('mom');
    window.location.href = ui.item.value;
}
}); 
});
Erigeron answered 27/9, 2012 at 22:56 Comment(2)
What do you want to return if not a List<string>?Pule
@LewsTherin I want to return Json that the Autocomplete plugin accepts, so I display a string (Name) and redirect the user based on the ID (int).Erigeron
C
7

Actually, autocomplete works fine with a source that returns just an array of strings. This should work fine for you, without modifying your controller action:

JavaScript:

$(document).ready(function () {
    $("#find-child-box").autocomplete({
        source: function (request, response) {
            // define a function to call your Action (assuming UserController)
            $.ajax({
                url: '/Admin/AutoCompleteMyChildren', 
                type: "POST", 
                dataType: "json",
                // query will be the param used by your action method
                data: { query: request.term },
                success: response
            });
        },
        minLength: 1, // require at least one character from the user
        select: function(event, ui) {
            alert(ui.item.ID);
            window.location.href = ui.item.value;
        }
    }); 
});

Check the overview tab of jQueryUI autocomplete to see what kind of data the widget expects.

Per your comment:

As @Alex hints at you'll have to change the data the controller action. You could create the correct object array using something like:

return Json(listfromDB.Select(c => new { label = c.Name, ID = c.ID }));

Which should generate JSON looking like this:

[{ label: 'Scott', ID: '1234' }, ...]

Which autocomplete can use correctly. Then, any time ui.item is available inside of autocomplete's event handlers (select for example), you should be able to access ui.item.ID.

Chaddie answered 28/9, 2012 at 2:22 Comment(5)
@Andrew_Whitaker - yes, that's true, however, I want to not use the string for the select, but the id. That means I no longer just have a string array. Hence, why I need to change the action and get the jQuery to accept the Name / ID pair.Erigeron
@ScottJ.: Okay, that makes more sense. I'll update my answer shortly.Chaddie
@Andrew_Whitaker - The controller code makes sense, but the "success" isn't even getting fired now. I've checked that the controller returns 3 items. What do I need to change on the jQuery side of things to make it work?Erigeron
@ScottJ.: Hmm, are there any JavaScript errors on the page? What if you do success: function (data) { console.log('success'); response(data); }, do you see the message logged?Chaddie
@Andrew_Whitaker - Sweet! That worked. For some reason, the extra stuff it was doing caused it to break. I removed the previous success portion with success: function (data) { response(data); } and it worked! I figured that it would display the ID as well as name, but it didn't. Thanks!Erigeron
D
1

Try creating list that stores your Child type

List<Child> children = new List<Child>();

 foreach (Child c in listfromDB)
{

      children.Add(c);

}

 return Json(children);

You will probably need ot revist your from end code as the Json will be different.

If you do not want all of the properties of the Child from the DB , then create a custom class and add what you want.

class CustomChild{

   public string Name {get; set;}
   public int ID { get; set ;}


}

List<CustomChild> children = new List<CustomChild>();

 foreach (Child c in listfromDB)
{

      children.Add(new CustomChild{ Name = c.Name, ID = c.ID} );

}

You may need to massage the syntax to get it to work or add some references. I encourage you to look into LINQ.

Decca answered 27/9, 2012 at 23:12 Comment(3)
I did as you suggested, however, the jQuery code isn't triggered anymore. Do I need to change the response function somehow? Thanks.Erigeron
I mentioned that you might need to adjust the front end code but I mispelled front to from....Decca
Use chrome dev tool net panel Nd console to see what the json looks like and why the JavaScript function is not firing .Decca

© 2022 - 2024 — McMap. All rights reserved.