Quando se recebe do servidor uma lista muito grande de dados (por exemplo, uma lista de itens de uma tabela do banco de dados ou um resultado de pesquisa), é necessário que esses dados sejam exibidos aos poucos ao usuário, em um formato de leitura fácil.
Neste artigo, iremos mostrar um script que lê um arquivo Json do servidor e monta uma tabela com esses dados, podendo escolher quantos itens essa tabela terá e distribuindo os itens em várias páginas.
Para conseguir isso, teremos que seguir algumas regras na construção de nossa página web. Em primeiro lugar, teremos que adicionar à página alguns campos ocultos onde armazenaremos a pagina atual, a quantidade de items por página, por qual atributo a tabela será ordenada e a quantidade total de itens:
<input type="hidden" name="pagina" value="${pagina}"> <input type="hidden" name="items" value="${items}"> <input type="hidden" name="ordem" value="${ordem}"> <input type="hidden" name="max" value="${max}">
Como falamos anteriormente, os dados serão recebidos do servidor através de um arquivo json. Para isso, usar a função $.ajax() do jQuery para ler esse arquivo, passando como parâmetro os valores dos campos ocultos acima. Assim, quando mapear o arquivo json, tenha em mente que você precisa ler esses dados. Caso esteja usando Spring, pode implementar em seu construtor um método como esse:
@RequestMapping(value="listagem.json", method=RequestMethod.GET) public ModelAndView listagem_json(@RequestParam("pagina") String pagina, @RequestParam("items") String items, @RequestParam("ordem") String ordem) { ModelAndView mav = new ModelAndView(); mav.setViewName(this.getName()+"/listagem"); mav.addObject("lista", serv.listagem(pagina, items, ordem)); return mav; }
Na página web, além dos campos ocultos, devemos ter as seguintes estruturas:
tabela onde os dados serão exibidos
<table class="bordered"> <thead> <th class="col" data-property="..."> ... </th> </thead> <tbody class="content"> ... </tbody> <tfoot> <td class="comando" data-nome="..." data-action="..."> ... </td> </tfoot> </table>
Nesta tabela, a tag thead deverá listar, através das tags th, os atributos da entidade que será exibida (o valor de property corresponde ao nome do atributo e o conteúdo da tag será o valor a ser exibido).
A tag tbody será preenchida dinamicamente com os valores do arquivo json. Finalmente, a tag tfoot não será exibida, e serve apenas para listar comandos que poderão ser aplicados a cada item da tabela (eles serão adicionada à coluna com property=”” e terão a string
/<id_do_elemento>
adicionada ao final do valor de action).
grupo de botões para escolher quantidade de itens por página
<div class="btn-group"> <button type="button" class="btn btn-default items">10</button> <button type="button" class="btn btn-default items">20</button> <button type="button" class="btn btn-default items">30</button> <button type="button" class="btn btn-default items">40</button> <button type="button" class="btn btn-default items">50</button> </div>
Aqui o importante a ser observado é que a tag button deve ter a classe items.
caixa de seleção para escolha de atributos
<div class="btn-group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> Ordem <span class="caret"></span> </button> <ul class="dropdown-menu dropdown-menu-right" role="menu"> <c:forEach var="attr" items="${atributos}" varStatus="status"> <li><a class="ordem" href="${status.index}">${attr}</a></li> </c:forEach> </ul> </div>
Nesta estrutura, listaremos os atributos da entidade que estamos visualizando (esses atributos serão as colunas da tabela). Selecionando uma das opções da lista, mudaremos a ordem pela qual os itens são mostrados na tabela.
lista de páginas disponíveis
<div align="center"> <ul class="pagination"></ul> </div>
Essa estrutura será preenchida dinamicamente, assim é importante que ela possua a classe “pagination“.
O Script
Após ter finalizado a construção da página, vamos agora ver como implementar script que fará o trabalho.
Dentro de um arquivo *.js (que estamos chamando aqui de page_load.js), devemos ter as seguintes funções:
- load_page(…): lê o arquivo json e adiciona os itens à tabela
- load_pagination(…): adiciona os links para as páginas, de acordo com o número total de itens e o numero de itens por página
- Ler os valores dos campos ocultos
- Ler o arquivo json, passando o valores lidos no item 1 como parametros
- Para cada item do arquivo json, adicionar a tabela uma nova linha, considerando o seguinte:
- cada atributo do item deve ser uma coluna da tabela
- se o valor de property for igual a #, deixar o conteúdo da coluna em branco
- se o valor de property for igual um valor em branco, adicionar os comando listados na tag tfoot.
O código para essa função deve se parecer com o seguinte:
function load_content(lista, target) { var atributos = []; $(".col").each(function(){ var property = $(this).data('property'); atributos.push(property); }); var pagina = $('input[name=pagina]').val(); var items = $('input[name=items]').val(); var ordem = $('input[name=ordem]').val(); var url = lista; $.ajax({ type: 'GET', url: url, data: {pagina: pagina, items: items, ordem: ordem} }).done(function(data){ var json = jQuery.parseJSON( data ); target.find("tbody.content").empty(); $.each(json.item, function(index, item){ var row = $('<tr>'); var counter = 0; for(var i=0; i<atributos.length; i++) { if(atributos[i] == '#') { row.append('<td></td>'); } else if(atributos[i] == '') { var col = $('<td>'); $(".comando").each(function(){ var nome = $(this).data("nome"); var action = $(this).data("action"); col.append('<button type="button" class="btn btn-sm btn-primary action" data-target="'+nome+'" data-action="'+action+'/'+item.id+'">'+nome+'</button>'); }); row.append(col); } else { var token = item[atributos[i]]; row.append('<td>'+token+'</td>'); } } target.find("tbody.content").append(row); target.find("tfoot").hide(); counter++; }); }); }
A função load_pagination irá ler o valor dos campos ocultos max e itens e irá adicionar à estrutura correspondente uma lista de links para as páginas disponíveis. O código para essa função será aproximadamente o seguinte:
function load_pagination() { $('.pagination').empty(); var max = $('input[name=max]').val(); var items = $('input[name=items]').val(); //var paginas = Math.floor(max / items); var paginas = Math.round(max / items); if(paginas == 0) paginas = 1; $('.pagination').append('<li><a href="#left">«</a></li>'); for(var i=0; i<paginas; i++) { var pagina = i+1; $('.pagination').append('<li><a class="pagina" href="#">'+pagina+'</a></li>'); } $('.pagination').append('<li><a href="#right">»</a></li>'); }
Finalmente, precisamos tratar o evento click de cada uma das estruturas auxiliares que adicionamos a nossa página. Basicamente, cada função irá alterar o valor do campo oculto correspondente e irá recarregar a tabela. O código dessas funções seria o seguinte:
$(document).on('click', '.items', function (event) { event.preventDefault(); var items = $(this).text(); $('input[name=items]').val(items); $('input[name=pagina]').val("1"); var lista = $('input[name=lista]').val(); load_content(lista, $('table.bordered')); load_pagination(); }); $(document).on('click', '.ordem', function (event) { event.preventDefault(); var ordem = $(this).attr('href'); $('input[name=ordem]').val(ordem); var lista = $('input[name=lista]').val(); load_content(lista, $('table.bordered')); }); $(document).on('click', '.pagina', function (event) { event.preventDefault(); var pagina = $(this).text(); var link = $(this).attr('href'); var max = $('input[name=max]').val(); if(link == '#left') { var temp = $('input[name=pagina]').val(); if(temp > 1) temp = temp - 1; $('input[name=pagina]').val(temp); } else if(link == '#right') { var temp = $('input[name=pagina]').val(); if(temp < max) temp = temp + 1; $('input[name=pagina]').val(temp); } else { $('input[name=pagina]').val(pagina); } var lista = $('input[name=lista]').val(); load_content(lista, $('table.bordered')); });