6
respostas

Filtro em Javascript

Fala pessoal!

Eu tenho na minha aplicação um sidebar(menu) lateral onde preciso implementar um input de campo de busca com keyup, que mostre apenas os links conforme o input, ou seja, a ideia é colocar um campo de filtro no qual digitarei parte do texto que está nos links, e todos os links que possuírem o textxo serão exibidos, enquanto os demais serão omitidas da página.

No curso de Angular I, o Flavio ensinou a usar o filter do javascript com o pipe na diretiva, entretanto, o meu menu não possui as diretivas NgFor ou NgRepeat, sendo assim, não consegui implementar.

Procurando aqui no fórum, na postagem https://cursos.alura.com.br/forum/topico-filtro-de-produtos-65961 na resposta da pergunta do aluno, o professor diz que dá pra filtrar no HTML mesmo, escondendo ou exibindo as linhas da tabela com CSS.

Enfim, alguém pode me dar alguma ideia de como implementar essa funcionalidade ? Se não dá pra usar mesmo o filter do JS ou se pelo HTML eu consigo fazer ou alguma outra ideia que possa me ajudar?

Valeu obrigado!!

https://cursos.alura.com.br/forum/topico-filtro-de-produtos-65961

3 - Filtra no HTML mesmo escondendo ou exibindo as linhas da tabela com CSS.


<aside class="left-sidebar">
    <div class="scroll-sidebar">

        <nav class="sidebar-nav">
            <ul id="sidebarnav">


            <nav class="navbar">
                    <input 
                    class="form-control" 
                    type="text" 
                    name="search" 
                    [(ngModel)]="filter"

                    >

            </nav>


                <!-- | filter:search -->

                <li class="nav-small-cap">INÍCIO</li>
                <li [class.active]="showMenu === '/dashboard'">
                    <a routerLink="/dashboard/dashboard1" [routerLinkActive]="['router-link-active']">
                        <i class="mdi mdi-gauge"></i>
                        <span class="hide-menu">Dashboard </span>
                    </a>
                </li>
                <li *ngIf="authService.roleMatch(['Administrador', 'Cadastro'])" class="nav-small-cap">CADASTROS</li>

                <!-- Inicio Nav Cadastros -->
                <li *ngIf="authService.roleMatch(['Administrador', 'Cadastro'])" [class.active]="showMenu === 'empresa'">
                    <a class="has-arrow waves-dark" (click)="AdicionarExpandirClass(['empresa'])" aria-expanded="false">
                        <i class="mdi mdi-account-card-details"></i>
                        <span class="hide-menu">Cadastros</span>
                    </a>
                    <ul aria-expanded="false" class="collapse" [class.in]="showMenu === 'empresa'">
                            <li>
                                <a routerLink="/cliente" [routerLinkActive]="['router-link-active']">Clientes</a>
                            </li>
                            <li>
                                <a routerLink="/empresa" [routerLinkActive]="['router-link-active']">Empresas</a>
                            </li>
                        <li>
                            <a routerLink="/estadocivil" [routerLinkActive]="['router-link-active']">Estado Civil</a>
                        </li>
                        <li>
                            <a routerLink="/fornecedor" [routerLinkActive]="['router-link-active']">Fornecedor</a>
                        </li>
                        <li>
                            <a routerLink="/uf" [routerLinkActive]="['router-link-active']">UF - Unidade da Federação</a>
                        </li>
                    </ul>
                </li>
                <!-- Fim -->

                <li *ngIf="authService.roleMatch(['Administrador', 'Financeiro', 'RelatorioContasReceber'])" class="nav-small-cap">FINANCEIRO</li>


</ul>
        </nav>
    </div>

</aside>
6 respostas

Fala aí Lucas, tudo bem? Bom, a ideia é o seguinte:

  1. Busque o input na página, isso pode ser feito com document.querySelector.
  2. Adicione o evento de click nele, isso pode ser feito com addEventListener.
  3. Busque os itens para serem filtrados, isso pode ser feito com document.querySelectorAll.
  4. A cada digito no input cria uma expressão regular para filtrar o conteúdo do li.
  5. Se der match adicione uma classe para esconder, se não, remove a classe.

Dá uma olhada no exemplo a abaixo:

https://jsfiddle.net/mahenrique94/rezu6fdc/1/

Espero ter ajudado.

Oi Lucas tudo bem?

Uma função javascript pura para filtrar elementos HTML é sempre mais rápida e perfomática. Dá uma olhada nesse exemplo que programei agora:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Filtro em HTML</title>
    <script>

        function Pesquisar(string) {
            tabela = document.getElementsByTagName("table")[0];
            linhas = tabela.getElementsByTagName("tr");
            for (let r = 1; r < linhas.length; r++) {
                dados = linhas[r].getElementsByTagName("td");
                let encontrei = false;
                for (let d = 0; d < dados.length; d++) {
                    if (dados[d].innerText.indexOf(string) >= 0) {
                        encontrei = true;
                        break;
                    }
                }
                if (encontrei) {
                    linhas[r].style.display = "";
                } else {
                    linhas[r].style.display = "none";
                }
            }

        }

    </script>
</head>

<body>
    <input oninput="Pesquisar(this.value)" placeholder="Pesquisar">
    <table>
        <tr>
            <th>Nome</th>
            <th>Idade</th>
            <th>País</th>
        </tr>
        <tr>
            <td>Jorge</td>
            <td>23</td>
            <td>França</td>
        </tr>
        <tr>
            <td>Luís</td>
            <td>50</td>
            <td>Brasil</td>
        </tr>
        <tr>
            <td>João</td>
            <td>56</td>
            <td>Itália</td>
        </tr>
    </table>
</body>

</html>

Espero ter ajudado!!!

Pessoal obrigado pelas respostas. Consegui implementar no código do André.

Entretanto estou com um problema. Fiz uma função para converter o campo de busca no input sem acentuação e com letras minúsculas. Com isso, converti também o conteúdo das tags (innerText) para comparar e filtrar:

Função remover maiúsculas e acentos:

removeMaiusculasAcentos(str) {
        str = str.replace(/[]/, "");
        str = str.replace(/[ÀÁÂÃÄÅ]/, "a");
        str = str.replace(/[àáâãäå]/, "a");
        str = str.replace(/[ÈÉÊË]/, "e");
        str = str.replace(/[éèê]/, "e");
        str = str.replace(/[ÍÌ]/, "i");
        str = str.replace(/[íì]/, "i");
        str = str.replace(/[ÓÒÔ]/, "o");
        str = str.replace(/[óòô]/, "o");
        str = str.replace(/[ÚÙ]/, "u");
        str = str.replace(/[úù]/, "u");
        str = str.replace(/[Ç]/, "c");
        str = str.replace(/[ç]/, "c");
        str = str.toLowerCase();
        //return str.replace(/[^a-z0-9]/gi, '');
        return str;
    }

Função de Pesquisar:

Pesquisar(string) {

        this.stringFormatada = this.removeMaiusculasAcentos(string);

        this.divPesquisa = document.getElementById("pesquisa");
        this.linhas = this.divPesquisa.getElementsByTagName("li");

        for (let r = 1; r < this.linhas.length; r++) {
            this.dados = this.linhas[r].getElementsByTagName("a");


            let encontrei = false;

            for (let d = 0; d < this.dados.length; d++) {

                this.dados[d].innerText = this.removeMaiusculasAcentos(this.dados[d].innerText);

                if (this.dados[d].innerText.indexOf(this.stringFormatada) >= 0) {
                    encontrei = true;
                    break;
                }
            }
            if (encontrei) {

                this.linhas[r].style.display = "";


            } else {
                this.linhas[r].style.display = "none";
                }
        }

    }

Acontece que ele está filtrando certinho, entretanto, no último If, quando ele mostra ou esconde as linhas do html, como os textos foram transformados, ele está mostrando na tela os links transformados, e não o texto original:

https://imgur.com/qKjdxrR

Eu tentei clonar a variável this.linhas em outra variável com somente as posições encontradas mas não consegui.

Alguma ideia ? Fiquei o dia inteiro nisso...rs

E obrigado pela resposta, me ajudou muuuuuito. =)

Acho que o problema está aqui, você está tirando os acentos no DOM. Use uma variável para guardar a informação ao invés de alterar o DOM. Se não resolver coloca seu código no github pra eu analisar melhor.

for (let d = 0; d < this.dados.length; d++) {

                let dadosInnerText=  this.dados[d].innerText;
              dadosInnerText= this.removeMaiusculasAcentos(this.dados[d].innerText);

                if (dadosInnerText.indexOf(this.stringFormatada) >= 0) {
                    encontrei = true;
                    break;
                }
            }

André deu certo!!

Muito obrigado pelo apoio cara, me ajudou muito. Só a linha abaixo faltou o indexOf, acho que vc esqueceu:

if (dadosInnerText.indexOf(this.stringFormatada) >= 0) { encontrei = true; break;

Muitíssimo obrigado!!

Disponha e bons estudos!!!