Recently I have seen a couple of posts describing how to implement autocomplete in an ASP.Net MVC application so I thought I would try it out. I got it working after a little trial and error so I thought I would try to outline my development process in hopes that the next person to try it out can save a little time. Here goes:

1. Download the Autocomplete plugin: http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/

2. Add the following files to your mvc app:

jquery.autocomplete.css

jquery.autocomplete.min.js

jquery-1.2.6.min.js

I added the files to a subdirectory of the Content folder.

 CropperCapture[1]

 

3. Add the following scripts in your page:

 

<script type="text/javascript" language="javascript" src="<%= Url.Content("~/Content/js/jquery-1.2.6.min.js") %>"></script>

<script type="text/javascript" language="javascript" src="<%= Url.Content("~/Content/js/jquery.autocomplete.min.js") %>"></script>

link href="~/Content/js/jquery.autocomplete.css" rel="stylesheet" type="text/css" />

I included these scripts in the head tag of my site's master page since I want the autocomplete functionality to be available throughout my site

 

4. Add an input element to your page:

<input id="txtStoryTags" type="text" class="largeTextbox" />

 

5. At this point it will probably be simplest to work backward. Here is the final code:

<script type="text/javascript">

$(document).ready(function() {
$('#txtStoryTags').autocomplete('<%=Url.Action("GetTags", "Listing") %>', {
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].Name, result: data[i].Name };
}
return rows;
},
formatItem: function(row) {
return row.Name;
},
delay: 40,
autofill: true,
selectFirst: false,
highlight: false,
multiple: true,
multipleSeparator: ";"
});
});

</script>

6. Documentation:

autocomplete( url or data, options )
Returns: jQuery

We first need to provide the function with a url which is quite easy in an ASP.Net MVC app:

$(document).ready(function() {
$('#txtStoryTags').autocomplete('<%=Url.Action("GetTags", "Listing") %>', ...

GetTags is an action in a controller named Listing that returns a JSON object constructed with an array of tag objects as its data. The names of these tags will be displayed in the autocomplete dropdown.

public ActionResult GetTags()
{
return Json(DataContext.GetTags(_topTags));
}
 
public class Tag
{
public int ID
{
get;
set;
}

public string Name
{
get;
set;
}

public int Count
{
get;
set;
}

The data returned by the server will look something like this:

[{"ID":11,"Name":"test1","Count":1},{"ID":12,"Name":"test2","Count":1},{"ID":13,"Name":"test3","Count":1}]
 

 

 

7. The trick is to convert this data to a format that the autocomplete function is expecting. If you are using local data, autocomplete expects an array of strings. Since our data is in the form of a JSON object, we will use the parse option to format our JSON object into data that the autocomplete function can work with.

                parse: function(data) {
var rows = new Array();
for (var i = 0; i < data.length; i++) {
rows[i] = { data: data[i], value: data[i].Name, result: data[i].Name };
}
return rows;
},

The parse function is not documented very well but it basically will take our JSON object and return an array of objects that consist of three mandatory parts:

1. data: this is an entire item in my JSON object: {"ID":13,"Name":"test3","Count":1}

2. value: this is the value I want displayed: test3

3. result: this is the value I want added to my input (txtStoryTags) after I select the tag from the dropdown: test3

 

8. The bulk of the work is done. Here are some other options I included:

                formatItem: function(row) {     (Takes a row of data returned by the parse function and returns 
return row.Name; a string to display in the autocomplete dropdown)
},
delay: 40, (400ms is default, seems too slow)
selectFirst: false, (First value is always selected if true, makes it tricky to type in new tags imo)
multiple: true, (mandatory for tags)
multipleSeparator: ";" (also good for tags, I think you can only specify one separator)

 

So why is there a formatItem function and a value member in the row data returned by parse? I think it is because value is the default and must be simple data, but formatItem can return something like row.Name + " (" row.Data.Count + ")" or something along those lines. If you want to see a full list of these mysterious options you can find them here:

http://docs.jquery.com/Plugins/Autocomplete/autocomplete#toptions
 

9. Last step, time to try it out! If you are not seeing any data, make sure the css file is included properly. You can go into the file and easily change the look and feel of the dropdown if you wish. Also, you should be able to step through the parse function to make sure the rows are in the proper format if you are still having trouble. Good luck!

CropperCapture[3]

Boo-yah!

 

Hope this helps you get those MVC apps looking fresh.

Joe