sábado, 2 de outubro de 2010

Auto complete em Asp.NET MVC

Olá pessoal, após muuiiiiitttooo tempo estou aqui novamente. Estou envolvido em um projeto que está tomando bastante meu tempo, mas estou bem satisfeito porque tivemos um ótimo resultado, e muitas coisas novas estão por vir. É um portal que traz o teatro até os internautas, e lugares onde provavelmente as peças nunca iriam chegar, agora têm-se a possibilidade de assistí-las, fico feliz por estar ajudando a levar a cultura para novos lugares. Caso tenham interesse, visite o portal http://www.cennarium.com/

Vamos ao problema: fazer um autocomplete que quando a pessoa comece a digitar ele vá até o servidor e traz alguns resultados.
Tecnologia usada: ASP.NET MVC 2 e Entity Framework.

Eu fiquei impressionado com a facilidade que tive de fazer usando post do jquery e Json do Asp.net mvc.

Vamos aos passos:

1) No seu controller, crie uma ação para retornar os dados de sua pesquisa, e faça que ela receba apenas quando a requisição for POST. No meu caso vou chamar o controller de AutoComplete, e minha ação chamará Cars, pois nela retornarei apenas o auto-complete para carros:

[HttpPost]
public ActionResult Cars(string search)
{
      string[] cars = carList.Where(c => c.Name.ToLower().StartsWith(search)).Select(c => c.Name).ToArray();
      return Json(cars);
}

Vamos explicar o que fiz na ação: apenas consulto meu repositório (nesse caso um fake repositório), e retorno um array de string (nomes dos carros encontrados na pesquisa), esse array eu retorno no formato de Json para minha View, sim, é o que você está imaginando, você pode retornar qualquer objeto .NET por Json, e ele converte tudo para você automaticamente.

Apenas por questão de teste, crie uma classe na sua pasta Models da seguinte maneira:

public class Car
{
        public string Name{get;set;}
}

E no construtor do seu controller adicione:

public AutoCompleteController()
{
     carList = new List<Car>();
     carList.Add(new Car { Name = "Ferrari" });
     carList.Add(new Car { Name = "Gol" });
     carList.Add(new Car { Name = "KA" });
     carList.Add(new Car { Name = "Vectra" });
     carList.Add(new Car { Name = "Hilux" });
     carList.Add(new Car { Name = "Celta" });
     carList.Add(new Car { Name = "Lamborghini" });
     carList.Add(new Car { Name = "S10" });
     carList.Add(new Car { Name = "New Civic" });
}

2) Adicione os scripts necessários para sua View, serão eles:

jquery-1.4.2.min.js (pode baixá-lo em http://jquery.com/)
jquery.autocomplete.min.js (pode baixá-lo em http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/)

3) Faça o método em javascript para buscar os dados no servidor:

Agora que entrará a técnica de usar o post do jquery, abaixo a função:

<script type="text/javascript">
       function carsAutoComplete(searchValue) {
              if (searchValue != "") {
                     $.post("/AutoComplete/Cars", { search: searchValue }, function (result) {
                              $(".carsAutoComplete").autocomplete(result);
                      });
              }
        }
</script>

O que estou fazendo aqui é o seguinte, o meu valor da consulta virá por parâmetro, se esse valor for diferente de vazio então chamo a ação do meu controller ("/AutoComplete/Cars"), passo o parâmetro a ser pesquisado ({ search : searchValue }) repare no mesmo nome do parâmetro da ação, isso faz com que o Asp.NET MVC atribua o valor automaticamente para a função, e o retorno eu o pego em uma função delegate (function(result) { ...) result será automaticamente meu vetor em javascript, o Json(cars) fará automaticamente isso pra mim, nessa função eu digo que todos os controler que tenham a classe carsAutoComplete ($(".carsAutoComplete")) deverão ser autocomplete e os valores a serem completados serão o resultado da pesquisa.

4) Indique o campo que receberá o autocomplete, juntamente com a ação que chamará o autocomplete, porém o class tem que ter o carsAutoComplete:

<input type="text" class="carsAutoComplete" onkeypress="carsAutoComplete(this.value)" />

Pronto!!! Seu autocomplete está pronto.

Até a próxima.