Una de las cosas que mas gustan de ASP.NET MVC es la posibilidad de utilizar librerias como jQuery de manera muy facil, vamos a utilizar el plugin Autocomplete para jQuery diponible en http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/.
Antes que nada para poder utilizar el plugin debemos referenciar los archivos correspondientes en nuestro SiteMaster, en la declaración del head de la pagina colocamos:
<%--jQuery Core --%> <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script> <%--end jQuery Core--%> <%--jQuery Autocomplete--%> <link href="../../Scripts/jquery.autocomplete.css" rel="stylesheet" type="text/css" /> <script src="../../Scripts/jquery.autocomplete.js" type="text/javascript"></script> <%--end jQuery Autocomplete--%>
Ya que tenemos las referencias, vamos a crear el controlador que nos servirá como proveedor de datos:
public ActionResult Completer(string q) { if (q != "") { NWDataContext db = new NWDataContext(); var suggest = from i in db.Customers .Where(e => e.ContactName.ToLower().StartsWith(q.ToLower())) select (i.ContactName + "|" + i.CustomerID); return Content(String.Join("\n", suggest.ToArray())); } return new EmptyResult(); }
Esta ActionResult recibe como parámetro un string q, que sera enviado por el Autocomplete Plugin al momento que el usuario empiece a llenar el TexBox. Verificamos si la q no esta vacia (”" – solo por si acaso), instan ciamos nuestro proveedor de datos o repositorio, en mi caso es un DataContext de LINQtoSQL, y realizo la busque en la tabla Customers donde el contact name empiece con q.
NOTA: pase todo a Lower para evitarme un posible dolor de cabeza con el case sensitive.
Al final retorno un arreglo con este formato para cada elemento:
Ana Trujillo|ANATR
Antonio Moreno|ANTON
Ann Devon|EASTC
Aria Cruz|FAMIA
André Fonseca|GOURL
Annette Roulet|LAMAI
Alexander Feuer|MORGK
Alejandra Camino|ROMEY
Art Braunschweiger|SPLIR
Anabela Domingues|TRADH
Ustedes no necesariamente deben utilizar este tipo de estructura, también pueden utilizar JSON si lo desean.
Con este método nos basta para realizar muchas cosas, vamos a implementar 5 variantes de este autocomplete:
- Autocomplete Simple.
- Autocomplete Multiples Selecciones.
- Autocomplete Incluyendo el ID del elemento elegido en un campo Oculto.
- Autocomplete Forzando la seleccion de uno de los sugeridos.
- Autocomplete Con Imagenes (Fancy).
AutoComplete Simple
Lo que corresponde de HTML, generar el texbox con la ayuda de los helpers de MVC.
<span>Autocomplete Simple</span>
<hr />
<% =Html.TextBox("Clientes") %>
Y setear el Autocomplete dentro de un SCRIPT TAG.
<script type="text/javascript"> $(function() { $('#Clientes').autocomplete(' <% =Url.Action("Completer","Home") %>', { width: 300, formatItem: formatItemNoID, formatResult: formatResult }); }); </script>
$(’#Clientes’).autocomplete setea el comportamiento del input con ID Clientes, para que sea autocompletado.
El primar parametro del autocomplete es la url, que como ven utilice el helper de MVC para que me genere un link hacia el ActionResult “Completer” del Controlador “Home”, la q es adjuntada como queryString al URL que le proporcionen, al final seran links de este tipo:
http://localhost/Home/Completer?q=a&limit=10×tamp=1254590546937, el limit es la cantidad de resultados que serán sugeridos al usuario por defecto 10 elementos.
El segundo parámetro es una colección de opciones con figurables que trae el plugin, no entrare en detalle ya que todas las opciones son bastante digeribles a la primera, pero si les dejo una url donde pueden ver todas las opciones disponibles: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions.
Lo que si voy a explicar son las funciones para parsear el resultado del autocomplete:
function formatItem(row) { return row[0] + " (<strong>id: " + row[1] + "</strong>)"; } function formatItemWIMG(row) { return "<img src='../../Content/img/es.jpg'/> " + row[0]; } function formatItemNoID(row) { return row[0]; } function formatResult(row) { return row[0].replace(/(<.+?>)/gi, ''); }
Lo que realizan estas funciones es dar forma a la lista de sugerencias del autocomplete, ya sea que queremos ver imágenes, formatear el texto, en general la forma en que se ve la lista.
Autocomplete Multiples Selecciones
Acá la diferencia es que se pueden seleccionar mas de un elemento, separados por comas.
<span>Autocomplete Multiples Selecciones</span><br />
<hr />
<% =Html.TextArea("ClientesMultiples") %>
<br />
<br />
$('#ClientesMultiples').autocomplete(' <% =Url.Action("Completer","Home") %>', { width: 300, multiple: true, formatItem: formatItemNoID, formatResult: formatResult });
La diferencia esta al configurar el autocomplete, ahora la opción multiple es TRUE.
Autocomplete Incluyendo el ID del elemento elegido en un campo Oculto
Algunas veces lo que necesitamos es el ID del cliente, así que ahora cuando configuramos el autocomplete utilizamos el evento .result (se ejecuta cuando el usuario selecciona algún elemento de la lista sugerida).
Ahora cuando el usuario selecciona Ana, ademas de completar la palabra en el primer texbox, el ID de Ana sera colocado en la casilla de la derecha.
<span>Incluyendo el ID en un campo Oculto</span>
<hr />
<% =Html.TextBox("ClienteName") %> <% =Html.TextBox("hiddenID", null, new { style = "width:50px", disabled = "disabled" })%>
<br />
<br />
$('#ClienteName').autocomplete(' <% =Url.Action("Completer","Home") %>', {
width: 300,
formatItem: formatItem,
formatResult: formatResult
});
$('#ClienteName').result(function(event, data, formated) {
$('#hiddenID').val(data[1]);
});
En esta sección le agregue el evento result, y acá le indico que cuando el usuario seleccione algún elemento, envié el id seleccionado al campo oculto.
Porque data[1]?
data representa el elemento seleccionado, al parsearlo data[0] venrdia siendo el nombre del cliente y data[1] el ID del mismo. Recuerden que en el controlador devuelvo un array de esta forma:
Nombre del Cliente | ID
Que en este contexto es:
Data [0] | Data[1]
Autocomplete Forzando la seleccion de uno de los sugeridos
SI lo que queremos es que el usuario no nos este inventando nombres de clientes, podemos setear el autocomplete para que solo acepte elementos existentes dentro de los sugeridos, si el usuario escribe cualquier otra cosa que no hace match con algún nombre de cliente existente, se resetea el texbox.
En lo personal no me agreda mucho esta opcion, me parece algo agresivo con el usuario limpiar todo lo que ha escrito sin enviarle algún mensaje de lo que esta pasando.
Para lograr este efecto simplemente colocamos la opcion mustMatch: true.
$('#ClientesForced').autocomplete(' <% =Url.Action("Completer","Home") %>', { width: 300, mustMatch: true, formatItem: formatItem, formatResult: formatResult });
Autocomplete Con Imagenes (Fancy)
Ya como últimos punto, si queremos lograr algo mas llamativo imaginen que tuviésemos a disposición una imagen del rostro de los clientes, entonces podemos desplegar en las sugerencias junto con el nombre una imagen del cliente.
<span>Autocomplete Con Imagenes</span><br />
<hr />
<% =Html.TextBox("ClienteFace") %>
$('#ClienteFace').autocomplete(' <% =Url.Action("Completer","Home") %>', {
width: 300,
formatItem: formatItemWIMG,
formatResult: formatResult
});
Acá lo único distinto es la función que utilizamos para darle formato a los elementos formatItemWIMG.
Pueden descargar el proyecto de ejemplo aqui






Hola, muchas gracias por el post. Me viene al pelo!!!!
Saludos
de nada amigo, un gusto que te halla servido …
Buenísimo,.. excelente trabajo,…! super útil