Criando um CRUD com THF (3/7) - Pesquisando pelos nossos clientes

Jhosef Marks
TOTVS Developers
Published in
9 min readFeb 5, 2019

Olá mundo!

Objetivo

Implementar o mecanismo de pesquisa em nossa tela de listagem de clientes deixando-a mais funcional.

Lista de posts da série “Criando um CRUD com THF”

Essa lista pode sofrer alterações até o final da série. 😅

Pré-requisitos

Não deixe de ler os posts anteriores (parte 1 e 2), seria ótimo para um melhor entendimento.

Para continuar do ponto anterior, basta clonar o projeto com o que já foi implementado.

git clone --branch post-2 https://github.com/jhosefmarks/sample-thf-crud-customers.git <sua-pasta-de-trabalho>

Passo 1 — Montando nossa pesquisa

Vamos abrir o arquivo customer-list.component.ts e criar a propriedade searchTerm, que será responsável por armazenar o termo que o usuário quer usar como pesquisa em nossa página.

Além disso, vamos criar uma propriedade chamada filter do tipo ThfPageFilter, que é responsável por exibir o campo de pesquisa no cabeçalho de nossa página e disparar as funções que precisamos.

Por enquanto, vamos chamar diretamente a função que já criamos para buscar os dados do nosso backend (loadData). Dessa forma, já conseguimos ver diferenças visuais em nossa página.

Por último, vamos alterar a linha que monta a url de carga na função loadData, ou seja, vamos alterar como urlWithPagination é inicializada.

A partir de agora, além da página também estamos enviando o que o usuário digitar no campo de pesquisa.

Inclusão das propriedade searchTerm e filter.

Não podemos esquecer de atualizar o componente thf-page-list no arquivo customer-list.component.html com a propriedade t-filter.

Adição da propriedade t-filter.

Com isso, o visual da nossa página ficará dessa forma:

Listagem de clientes com pesquisa.

Notem que nossa página continua trazendo os resultados, mas a busca em si ainda não está funcional, pois a nossa paginação não está sendo tratada da forma correta e não estamos limpando os dados apresentados anteriormente.

Requisição com o termo de pesquisa, mas sem a paginação correta.

Temos dois problemas para resolver:

  • corrigir a paginação, sempre que efetuarmos uma nova pesquisa precisamos buscar a primeira página dos resultados retornados, e quando carregar uma nova página, precisamos re-enviar o termo pesquisado novamente para não buscarmos dados diferente do que queremos;
  • precisamos limpar a lista de clientes quando uma nova pesquisa for feita, ou seja, quando for a primeira página, nós devemos zerar a nossa lista de cliente, caso contrário precisamos concatenar o resultado.

Antes de tudo, vamos criar uma nova função que será chamada quando o usuário fizer uma pesquisa.

Função onActionSearch.

E agora, vamos criar a função showMore e fazer com que a propriedade t-show-more do thf-table passe a chamar essa função, assim, quem passa a ser responsável por chamar nossa função que faz a requisição para o servidor (loadData) é a nova função e não o thf-table diretamente, dessa forma, ela que controla qual a próxima página que deve ser chamada.

Função showMore.

Não esqueça de atualizar o thf-table.

Evento t-show-more atualizado.

Se você percebeu a função loadData, vai precisar de um refactory, já que ela deixa de ser responsável só pelo controle de paginação e passa a lidar com mais parâmetros.

Refactory da função loadData.

Note que agora, loadData não controla mais as páginas que devem ser exibidas, também deixamos de controlar os parâmetros diretamente na url e passamos a mandar os query parameters (ou query string) como parâmetro para a função get do HttpClient fazer a concatenação necessária.

Com isso, nossa função de pesquisa rápida passa a funcionar 100%.

Função de pesquisa rápida 100% funcional.

Passo 2 — Criando a pesquisa avançada

Agora que já temos nossa pesquisa rápida funcionando 100%, vamos criar nossa pesquisa avançada, onde o usuário poderia ter mais opções de pesquisa.

Importante: o uso de uma modal nem sempre é ou será a sua melhor opção, para fins de estudo e, para a maioria dos casos, isso já é suficiente; mas sinta-se a vontade para implementar a sua busca avançada da maneira que achar melhor.

Vamos iniciar criando um modal em nossa aplicação, abra o arquivo customer-list.component.html e inclua o thf-modal. Crie uma propriedade chamada #advancedFilter de referência para ele e configure o seu título.

Inclusão do thf-modal em nossa páginda.

Vamos criar uma função que irá abrir o nosso modal e atualizar a propriedade filter para que chame essa nova função quando o usuário quiser fazer uma pesquisa avançada, não se esqueça da propriedade que irá fazer referência ao modal que criamos no nosso template.

Inclusão da função openAdvancedFilter em nosso componente.

Com isso, já conseguimos habilitar a busca avançada e abrir um simples modal para preenchimento do usuário.

Página com abertura do modal funcionando.

Legal, mas agora vamos trabalhar em cima do nosso formulário de pesquisa.

Como vamos trabalhar com formulário e inputs, precisamos importar o FormsModule do angular em nosso SharedModule.

Isso não vai alterar em nada o visual do nosso projeto, então, vamos ao nosso formulário.F

No arquivo customer-list.component.html, vamos incluir alguns campos para pequisa dentro no nosso modal:

nome: vamos utilizar um thf-input, pode-se dizer que é o tipo de entrada de dado mais básico que existe e vai servir para fazer pesquisas por nome.

Inclusão do thf-input dentro do thf-modal.

Com isso, já teremos um resultado diferente em nosso modal.

Modal com campo para pesquisa por nome.

Se você preencher o campo e apertar o botão "OK", não vai ter nenhum retorno; mas não se preocupe. Nós vamos, primeiro, criar nosso formulário e depois vamos tratar de pegar esses dados e enviar para o nosso backend.

cidade: para esse campo, vamos usa o thf-combo, que é um campo que trás uma lista de valores pré-definidos que podem ser filtrados, bem próximo a um campo com autocomplete.

Modal com thf-combo.

Como o thf-combo precisa de uma lista pré-definida para o usuário poder escolher o valor desejado, você precisa definir essa lista no customer-list.component.ts em uma propriedade ou passar um serviço que tenha essa lista de dados, para o nosso exemplo, vamos criar nossa lista dentro do nosso código mesmo.

Lista de cidades que serão exibidas em nosso combo de pesquisa.

Com isso, nós teremos o seguinte resultado:

Modal com combo de cidade.

gênero: como o gênero tem poucas opções de escolha, em nosso exemplo vamos usar o thf-radio-group.

Adicionando o thf-radio-group no thf-modal.

Da mesma forma que o thf-combo, nós precisamos configurar a lista de opções que serão exibidas pelo thf-radio-group.

Configuração dos valores exibidos pelo thf-radio-group.

Olha o resultado aí…

Modal com o campo para seleção de gênero.

status: e para o campo de status vamos usar o thf-checkbox-group, pois o usuário vai poder escolher mais de uma opção.

Inclusão do thf-checkbox-group no thf-modal.

O thf-checkbox-group segue o mesmo conceito dos componentes anteriores. Vamos ter que definir uma lista de valores válidos.

Lista de opções para o thf-checkbox-group.

E com isso, o nosso formulário de pesquisa avançada está finalizado:

Modal com todos os campos de pesquisa configurados.

Agora, nós precisamos pegar os valores digitados pelo usuário e enviar para o nosso backend. Primeiro, vamos criar uma função que irá pegar os valores digitados pelo usuário e irá chamar nossa função loadData passando um objeto com esses valores.

Não podemos esquecer de criar no nosso componente as propriedades que estão ligadas ao ngModel dos nossos inputs.

Nova função onConfirmAdvancedFilter e novas propriedades.

Nossa pesquisa ainda não vai funcionar, pois faltou informar para o thf-modal que essa é a função que deve ser chamada ao confirmar a pesquisa avançada, para isso, vamos criar duas propriedades, uma para ação de confirmação e outra para a ação de cancelamento, caso o usuário desista de fazer a pesquisa avançada.

Definição das ações de confirmação e cancelamento da pesquisa avançada.

Agora, vamos configurar o thf-modal com essas novas propriedades.

Modal com as ações configuradas.

Com isso, nossa função de pesquisa avançada já está funcionando!

Pesquisa avançada funcionando.

Mas… sempre tem o mas 😅 A paginação está com problemas. Se clicarmos em "Carregar mais", os valores de pesquisa serão ignorados, então, precisamos salvar o que foi digitado ou o valor da última pesquisa avançada e enviar quando a função showMore for disparada pelo thf-table, para isso, vamos atualizar a função onConfirmAdvancedFilter para salvar os parâmetros e vamos atualizar a função showMore para enviar esses parâmetros quando o mesmo estiver preenchido.

Refactory nas funções que disparam nossas pesquisas.

Pronto e sem nenhum mas, nossa pesquisa avançadas está funcionando perfeitamente.

Passo 3 — Exibindo os filtros das buscas

Para deixar nossa busca ainda melhor, vamos incluir disclaimers em nossa página para o usuário saber o que está sendo filtrado, para isso vamos usar a propriedade t-disclaimer-group do thf-page-list.

Vamos criar uma propriedade em nosso componente e associar a mesma ao nosso thf-page-list.

Nova propriedade para controlar nossos disclaimers.
Disclaimer group adicionado ao page list.

Novamente, isso não fez nenhum efeito prático em nossa página, mas acalme-se. Queremos mostrar os disclaimers apenas quando existir alguma pesquisa ativa, quer seja ela rápida ou avançada.

Primeiro, vamos atualizar os disclaimers quando houver uma pesquisa rápida.

Disclaimer atualizado com o termo pesquisado.

Com as alterações, temos o seguinte resultado:

Notem que temos um pequeno problema. Ao excluir o disclaimer, nós não atualizamos nossa tabela. Para isso, nós precisamos refazer a pesquisa sem o filtro, para resolver esse problema precisamos criar uma função que faça isso e vincular essa nova função ao nosso objeto que controla o disclaimer.

Legal, mas temos um problema aqui e vale a pena parar para entender algumas coisas. Se você colocar um debugger dentro da função loadData, você vai perceber que ela está sendo disparada mais de uma vez. A primeira chamada acontece quando efetuamos nossa pesquisa, e a segunda acontece quando atualizamos o nosso grupo de disclaimers, fazendo com que a nossa pesquisa passe a funcionar de uma forma estranha.

O que acontece é que nosso disclaimer dispara o evento change a cada mudança, ou seja, quando recebe um disclaimer quando efetuamos uma pesquisa e quando o usuário remove um disclaimer.

Bom, isso pode parecer ruim, mas na verdade podemos usar a nosso favor. Mudando um pouco o fluxo de pesquisa nós podemos fazer com as pesquisas apenas atualizem o nosso grupo de disclaimers e quando o mesmo sofrer qualquer alteração nós disparamos a função loadData baseada no que tem no grupo de disclaimers.

Vamos ver o código refatorado.

Função onActionSearch e onChangeDisclaimerGroup refatoradas.

Agora, só falta acertar nossa pesquisa avançada da mesma forma e teremos nossa funcionalidade de pesquisa 100% funcional.

Função onConfirmAdvancedFilter refatorada.

Olha como o resultado final ficou bacana:

Existem outras formas de tratar o comportamento do disclaimer group, mas para o nosso exemplo, essa é a forma mais simples e prática de resolver e ainda tirar vantagem desse comportamento.

E agora José?

Agora, você pode brincar com o exemplo e adicionar novas formas de pesquisar criando filtros pré definidos entre outras opções. Uma outra ideia de implementação é limpar a pesquisa avançada quando o usuário faz a pesquisa rápida.

Você pode pegar os fontes atualizados no repositório do github. Fiz o possível para commitar passo a passo para que seja possível acompanhar a evolução do que fizemos até aqui.

No próximo post vamos começar a cadastrar nossos clientes. Vejo vocês por lá.

Referências e dicas de leitura

Documentação oficial do THF:

Documentação oficial do Angular:

--

--

Jhosef Marks
TOTVS Developers

Desenvolvedor por vocação, e front end por opção. Projeto atual: http://thf.totvs.com.br