Busca

quarta-feira, 27 de julho de 2011

Utilizando um Autocomplete do JQueryUI como picker a partir de uma lista de dados do servidor por Json

Bom galera, estreiando o blog com uma postagem sobre como utilizar um autocomplete do jqueryui para servir como um picker.

Vamos linkar o autocomplete com uma lista de dados vinda do servidor carregada por ajax do jquery, logo o retorno será em um formato json.

Chega de papo e vamos ao que interessa.




Vamos criar primeiramente o objeto html que será nosso picker


     <input name="pessoa" id="pessoa" />


No caso farei um picker de Pessoas

Agora no server side vamos criar nossa função que irá retornar os dados para a função ajax. No meu caso eu criei a função na própria página aspx que estou usando o picker, porém a função pode ficar em uma página diferente.



    [WebMethod()]
    public static string[] GetPessoas()
    {
        List pessoas = Pessoa.getAllCliente();
        var result = from s in pessoas
                     select s.Codigo.ToString() + " - " + s.Nome;
        return result.ToArray();
    }



Temos que herdar a função que irá retornar os dados de um WebMethod para poder ser interpretada pelo browser do cliente ao fazer uma requisição ajax.

Utilizei também um Linq para retornar os campos de interesse da minha List. Onde eu quero mostrar o código e o nome do cliente.

Para retornar os dados para o autocomplete a função deve retornar uma string e você faz um split via script ou retorna logo um array de string que será interpretado como uma estrutura Json.
Ao utilizar o ajax como mostrarei abaixo, retornando o array ele automaticamente armazena os dados na forma de Json no próprio cliente, ficando rápida as consultas para o autocomplete.

Eu não quis ir filtrando o que o usuário digita e após, por exemplo, 0.4 segundos fazer a pesquisa via ajax de depois disso linkar o resultado no autocomplete, pois isso demoraria mais ainda, pois se ele errasse a digitação e apagasse pra digitar novamente o ajax já teria disparado e geraria várias requisições para o servidor, ficando mais lento do que carregar de uma vez só todos os clientes no autocomplete.

Minha função Pessoa.getAllCliente() retorna em torno de 15 mil registros. Passando isso para o Json gira em torno de 2Mb de dados para o cliente via requisição ajax. Isso leva em torno de 5~10 segundos para ser armazenado no cliente via rede local. Isso se torna viável para a aplicação que tenho aqui na empresa, no caso uma Intranet.

Após toda essa explicação, vamos retornar os dados para o cliente e montar o nosso picker, para isso vamos utilizar a chamada $(document).ready() do jquery, pois precisamo que assim que possível no navegador do cliente já seja carregado todos os dados no picker e montar o autocomplete.



$.ajax({
    type: "POST",
    url: "Pagina.aspx/GetPessoas",
    data: "{}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(array) {
        if (array.d) {
            $(function() {
                $("#pessoa").autocomplete({
                   source: array.d,
                   delay: 400,
                   minLength: 3,
                   select: function(e, ui) {
                        $(this).blur();
                        var cod_pessoa = ui.item.value.split(" ").shift();
                        $('#content').show('slow');
                        $('#tabs-info').hide('slow').load("PaginaInfo.aspx?id=" + cod_pessoa, function() {
                            $(this).show('slow');
                        });
                   },
                   search: function(e, ui) {
                      $('#content').hide('slow');
                   }
                });
            });
        }
    },
    error: function(xhr) {
        alert(xhr.get_message());
    }
});



Vamos à explicação: Assim que a página esteja disponível fazemos uma chama ajax para trazer os dados da nossa função server side por uma url url: "Pagina.aspx/GetPessoas" passando vazio como parâmetro da função data: "{}", ou seja, se você precisar passar algum parâmetro para a sua função do server side você coloca ele ai no data, pode ser qualquer estrutura de dados a partir do cliente, inclusive um array, e claro também passamos o tipo da chamada como sendo json contentType: "application/json; charset=utf-8", dataType: "json".

Assim que terminar a chamada e o script montar os dados no cliente ele chama a função success do ajax e é aqui que montaremos no autocomplete. Na função success pegamos o retorno da chamada que é justamente os dados em forma de array json  success: function(array) . Os dados estão armazenados no atributo 'd' da variável 'array'.

Então verificamos se existe algum dado no array  if (array.d) e se existir montamos o autocomplete passando como parâmetro de dado justamente o 'array.d'

 $("#pessoa").autocomplete({
    source: array.d,
    delay: 400,
    minLength: 3

Até agora tudo está montado para que o campo pessoa seja um autocomplete comum, o que vai fazer o autocomplete se tornar um picker é fazermos que ao selecionar algum item dele o site faça alguma outra coisa.

Então implementamos a função select do autocomplete:
select: function(e, ui) {
    $(this).blur();
    var cod_pessoa = ui.item.value.split(" ").shift();
    $('#content').show('slow');
    $('#tabs-info').hide('slow').load("PaginaInfo.aspx?id=" + cod_pessoa, function() {
    $(this).show('slow');
});

Coloquei um blur no começo da função para ele perder o foco quando selecionar um cliente.
Para pegar qual o código do cliente selecionado eu faço um split com o valor selecionado, que é passado no parâmetro ui (segundo parâmetro da função select), e faço um shift() com o array retornado no split(), que nada mais é do que selecionar apenas o primeiro elemento do array e descartar o restante, pois eu fiz um split com " " espaço em branco, retornando por exemplo {"12345","-","Fulano de tal"}, lembrando que a string do array do json foi montada no server side.
Após selecionado o cliente em uma variável podemos fazer qualquer coisa com o cliente na página. Por exemplo, eu uso o código para carregar dinâmicamente várias divs no site. Coloquei um exemplo abaixo:

var cod_pessoa = ui.item.value.split(" ").shift();
$('#content').show('slow');
$('#tabs-info').hide('slow').load("PaginaInfo.aspx?id=" + cod_pessoa, function() {
$(this).show('slow');

Eu pego o código do cliente e carrego a página aspx PaginaInfo.aspx passando no get o código. Dentro da página PaginaInfo.aspx eu carrego informações pertinentes à esse cliente e mostro o resultado na div tabs-info que é um Pager do jqueryui também, com alguns efeitos de visibilidade.

No caso eu implementei a função search do autocomplete também, que irá esconder minha div content onde fica o conteúdo dessa página, essa função search é disparada quando o se pesquisa alguma coisa no autocomplete.
Para ficar bom também eu coloquei um $("#content).hide("slow");   no focus do picker também, essa função deve ser implementada fora do ajax, porém dentro do $(document).ready(). Também limpo o valor do picker quando ganha o foco, ficando assim:

$("#pessoa").focus(function() {
   $(this).val("");
   $('#content').hide('slow');
});


Bom pessoal, é isso! Espero que gostem da minha primeira postagem no meu blog.

Até qualquer hora.

Um comentário: