Tuesday, September 2, 2008

jQuery Autocomplete + JSON + ASP.NET MVC

It just took me a while to get this running, so maybe this could save you some time.

The requirement was to use the jQuery Autocomplete plugin to aid in the selection of some data coming from a database in an application using ASP.NET MVC Preview 4.

If you would like to see this plugin in action, refer to its demo page.

The documentation of the plugin states that when a remote source is used, the result must be returned formatted with one value on each line; but since I want to return a list of complex objects I would like to use JSON... googling around I've arrived to this page and learnt about the parse and dataType options that are not documented... using this options you can make the autocomplete plugin to receive remote data in JSON format.

So... this is the JS code that configures the plugin:

$(document).ready( function() {
$('#signalName').autocomplete('<%=Url.Action("Lookup", "Signal") %>', {
dataType: 'json',
parse: function(data) {
var rows = new Array();
for(var i=0; i<data.length; i++){
rows[i] = { data:data[i], value:data[i].SignalName, result:data[i].SignalName };
}
return rows;
},
formatItem: function(row, i, n) {
return row.SignalName + ' - ' + row.Description;
},
width: 300,
mustMatch: true,
});
});

Here, I specify that the rows in the drop down will have the "SignalName - Description" format, and that the value that will be put in the textbox is the SignalName property of the selected item... this is done with the value property of the rows array.

The ASP.NET MVC controller/action that provides the data will be something like this:

public class SignalController : Controller {
...
public ActionResult Lookup(string q, int limit)
{
var list = signalRepository.SearchByPage(q, 1, limit);
var data = from s in list select new {s.SignalName, s.Description};
return Json(data);
}
...
}

To get this running, don't forget to include the required javascript files and the css to style the autocomplete drop down. Refer to the documentation for more information.

That's all for now.

Submit this story to DotNetKicks

22 comments:

Anonymous said...

Great Post! could you poat the signalRepository code?

Germán Schuager said...

Hi, signalRepository is an instance of ISignalRepository and the signature of SearchByPage is:

IList<Signal> SearchByPage(string text, int first, int count)

The concrete implementation will be really out of scope since it is using NHibernate and custom session management classes.

For testing purposes you can just return a new List<Signal> instance.

Erik said...

As I get it, if you use Url.Action("Lookup", "Signal") you dont pass the string q to your Lookup method. Causing the server to always get all the Signal items, and you do the filtering on the client not on the server side. How can you pass the q param to the Signal/Lookup, and dont use Signal/Lookup/YourLookup?

Regards

Germán Schuager said...

Hi Erik,
It is handled by the autocomplete plugin.
Take a look a the demos.

Anonymous said...

hi German i liked your post but could you let me know that how can i load data from sql table and populate the values in the autocomplete using C# i am new to .net please.

James said...

Thanks, very helpful!

Anonymous said...

Thanks man. The non-native handling of the Json->row() was driving me nuts.

Perfect!

Rashmi said...

Auto-complete is not working for me. I am not sure what I am doing wrong. Any help is greatly appreciated!
I am trying to use auto-complete in ASP.NET MVC C# project
I have added the following code to site.Master page.

I have included all the javascripts from the demo.

$(document).ready(function() {

$("#tags").autocomplete(["c++", "java", "php", "coldfusion", "javascript", "asp"], {
width: 320,
max: 4,
highlight: false,
multiple: true,
multipleSeparator: " ",
scroll: true,
scrollHeight: 300
});
)};



Please, help me.

Germán Schuager said...

Hi Rashmi, it seems that your problem has nothing to do with C# or MVC... you are not using any server side funcionality.
You should take a look at the docs: http://docs.jquery.com/Plugins/Autocomplete
I'm sorry I can't help you more.

Rashmi said...

Thanks for your response. I am going to use server code to read the data from the database. For now, I am just hardcoding some value. The autocomplete function is called but I don't see any results displayed.

I tried to debug it using Firebug. I am getting the following error:
data[i].result is undefined
On this line:
if( data[i].result.toLowerCase() == q.toLowerCase() )

I was trying to post my code but it doesn't let me. Is There a way I can send the code?

Germán Schuager said...

You can send it to my email, but I think it would be better to try with the jQuery support forums... I'm very bussy at the time being and I don't think I can look at it in a timely fashion.
Regards.

Rashmi said...

I am using Jquery 1.3.2 plugin.Could that be a problem? It looks like auto-complete plugin works with older version

Anonymous said...

Hi,

I am using your auto-plugin example to configure it for JSON data. I am getting undefined - undefined value in the drop-down. I have changed the code to display Id and name. When i click on it, I get something like this:
[{"Id":330,"Name":"region: Western Sumatra"},{"Id":346,"Name":"Province: Tropical Northwestern Pacific"},{"Id":350,"Name":"Ecoregion: West Caroline Islands"}

Can you tell me what is going on?

Steve said...

Hey - I wanted to first thank you for your post, and also lead you to a post I just made.

Your post was great - but I had one big problem: I wanted to use a web service where ?q=[search parameter] was not an option for me.

If you control your own web service and make your own JSON great - but if you don't control it, I have a great hack to override the q= parameter.

You can check it out here:

http://1300grams.com/2009/08/17/jquery-autocomplete-with-json-jsonp-support-and-overriding-the-default-search-parameter-q/

Germán Schuager said...

Good to know Steve; I'll save a link to your post for future reference.
Regards.

Pawel said...

Does the result() callback work for you? I implemented the autocomplete like that in ASP.NET MVC and am returning JSON from the controller. I've added a result() callback but it is never called for some reason, I wonder whether it has something to do with how the plugin has been setup.

Anonymous said...

This would have taken me a considerable amount of time as I had already spent it doing some head scratching. Muchos Gracias.

Omri said...

For those of you having trouble getting this to work, after some trial and error we managed to get a working example that passes key/value pairs.

You can download the example project from here:

http://so.ca/2009/11/jquery-autocomplete-json-asp-net-mvc-key-value-pair-example/

Thanks so much Germán - you saved us a lot of time!

Andrej said...

How possible that such plugin contains no EVENTS like "onitemselect", etc?

Boby said...

You just saved my life :D

I was trying to get this plugin work with JSON and stuck for a few hours.

Thanks a lot!

Schulty said...

Thanks for this, I was having problems With the parsing as well!

DalSoft said...

Thanks clean example, however under MVC 2 you need to add JsonRequestBehavior.AllowGet as below:


return this.Json(data, JsonRequestBehavior.AllowGet);