Monday, July 23, 2012

MVC AutoComplete template

Get the Id/Key of the selected item and highlight the inputed text in the list of selections.
The below works with MVC3 or MVC4 using Razor view engine

I will use JQuery to enhance the UI of the app, so here is my autocomplete that can be used anywhere in your MVC project and more than once in a page.

First configure your scripts to include JQuery and JQuery UI, etc in the layout page, so the autocomplete can work all over the application in any view.
I added the autocomplete java code in the ("~/bundles/jqueryval") bundle, at the App_Start as below:
  public static void RegisterBundles(BundleCollection bundles)
            //TODO: On production this will be true
            BundleTable.EnableOptimizations = false;

            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(

            bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(

This ControlJscript.js file will be my stander control code for all the templates I need, currently its populated with the autocomplete code that will wire the autocomplete and the highlighted behavior

$(document).ready(function () {

    //set autocomplete with hieghlit text
    $(":input[data-autocomplete]").each(function () {
            source: $(this).attr('data-autocomplete'),
            minLength: 2,
            change: function (event, ui) {
                var TargetId = "#" + $(this).attr('data-target');    //find Target Control Id
                if (ui.item == null) {$(TargetId).attr('value', "  ");} //Set the value to the selected value
                else { $(TargetId).attr('value',;}
        }).data("autocomplete")._renderItem = function (ul, item) {
            var term = $(this)[0].term;
            var index = item.label.toLowerCase().indexOf(term.toLowerCase());

            return $("<li>li>")
                .data("item.autocomplete", item)
                .append("<a>" + item.label.substring(0, index)
                      + "<font class='AutoFont'>" + item.label.substring(index, index + term.length)
                      + "font>" + item.label.substring(index + term.length) + "a>")
            //&#8205 script joiner
            //u is the solution

 Note: AutoFont is a css class that specify the style for the input text
Second set Autocomplete View Model class in your model folder or anywhere you like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ADM.Ntrasal.UI.Web.Browser.Models
    public class AutoCompleteViewModule
        public AutoCompleteViewModule()
            //default values
            AutocompleteCount = 10;
            Type = AutoCompleteTypes.EmployeeNames;
        public string Id { get; set; }
        public string Name { get; set; }
        public string Field { get; set; }
        public int AutocompleteCount { get; set; }
        public AutoCompleteTypes Type { get; set; }

        public enum AutoCompleteTypes

I prefer to add the controller logic to an api controller, but for this example (for backwards compatibility) im adding the managing code to a normal controller as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ADM.Ntrasal.Business;
using ADM.Ntrasal.Data;
namespace ADM.Ntrasal.Web.UI.Browser.Controllers
    public class AutoCompleteController : Controller
         private readonly IRepositories Repositories;
         public AutoCompleteController()
        {  //Prefare to use Ioc but for simplicity
            this.Repositories = new Repositories();
        // GET: /AutoComplete/

        public ActionResult EmployeeNames(string term)
            var count = 10;
            var UserProfileRepostery = this.Repositories.Create<UserProfile>();

            var result = UserProfileRepostery.GetAll().Where(x => x.Employee_Name.ToLower().Contains(term.ToLower()))
              .Take(count).Select(x =>
                      label = x.Employee_Name,
                      id = x.UserID
            return Json(result, JsonRequestBehavior.AllowGet);

Note: the idea is to return the text with its key, so when the user selects something you get the id/key directly.

Add the below as a template for the Autocomplete
@model ADM.Ntrasal.UI.Web.Browser.Models.AutoCompleteViewModule
 <input type="text"  name="AutocompleteTextBox"
     data-autocomplete="@Url.Action(@Model.Type.ToString(), "AutoComplete", new { count = @Model.AutocompleteCount })"
     value='@Model.Name' />


Add it to your view whenever an autocomplete is neededset, for a test view, make the view a strong type with AutoCompleteViewModule as below.
@model ADM.Ntrasal.UI.Web.Browser.Models.AutoCompleteViewModule

I did’t add a code sample because this is a part of a large project, but if anybody is interested, I can make a quick project and upload it.

No comments:

Post a Comment