Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

O laço com forEach não funciona

Montei o laço do filtro com forEach e, por algum motivo ele não funciona. Por outro lado, montando com o for "normal" (assim como foi feito na aula) ele funciona sem problemas, segue abaixo o código que montei com forEach:


    var campoFiltro = document.querySelector("#filtrar-tabela");

    campoFiltro.addEventListener("input", function(){

    var pacientes = document.querySelectorAll(".paciente");

    if( this.value.length > 0){
        pacientes.forEach(function(paciente){
            var tdNome = paciente.querySelector(".info-nome");
            var nome = tdNome.textContent;
            var expressao = new RegExp(this.value,"i");
            if( !expressao.test(nome) ){
                paciente.classList.add("invisivel");
            }else{
                paciente.classList.remove("invisivel");
            }
        });
    }else{
        pacientes.forEach(function(paciente){
            paciente.classList.remove("invisivel");
        });
    }
});

Há algum motivo específico para isso? É algum bug do próprio JS?

Tks


Edit:

Acabei não explicando onde estava o problema exatamente, falha minha, mas segue abaixo:

A questão não chega a ser a listagem, que funciona perfeitamente, mas sim na hora de executar o teste da Expressão Regular if( !expressao.test(nome) ), que quando faço uso dela dentro do forEach retorna true para todos os casos e quando uso no for funciona sem qualquer problema.

O console não traz erro algum pois a listagem é executada e o teste é feito, o problema mesmo fica no retorno do teste que está funcionando de forma diferente dependendo da função que é usada para realizar o loop.

6 respostas

querySelectorAll retorna um HTMLCollection e não um Array. Você pode utilizar o for/in ou o forEach da seguinte forma:

Array.prototype.forEach.call(pacientes, paciente=> {

O que o Raphael disse é verdade, mas repare que nas últimas versões dos Browsers o objeto NodeList já pode usar a função forEach.

Conferindo este link da Mozilla Developer Network, ao final dele existe uma tabela de Browser Compatibility que mostra quais browsers já suportam.

Havia tentando da mesma forma e também não consegui. Somente com o for

Segue meu código:

var campoFiltro = document.querySelector("#filtrar-tabela");

campoFiltro.addEventListener("input", function() {
    var pacientes = document.querySelectorAll(".paciente");

    if (this.value.length > 0) {
        pacientes.forEach(function(paciente){
            var tdNome = paciente.querySelector(".info-nome");
            var nome = tdNome.textContent;

            if (nome != this.value) {
                paciente.classList.add("invisivel");
            } else {
                paciente.classList.remove("invisivel");
            }
        });

    } else {
        pacientes.forEach(function(paciente){
            console.log(paciente);
            paciente.classList.remove("invisivel");
        });
    }
});
solução!

O que acontece é que você utilizou o

var expressao = new RegExp(this.value,"i");

dentro do forEach.

Ao utilizar o forEach você passa uma função, anônima ou não, como callback. Isso faz com que você o escopo do this seja o da função de callback criada e não a função pai, criada para definir o addEventListener.

O correto seria vc fazer assim:

var campoFiltro = document.querySelector("#filtrar-tabela");

    campoFiltro.addEventListener("input", function(){

    var pacientes = document.querySelectorAll(".paciente");

    if( this.value.length > 0){
        var inputValue = this.value;
        pacientes.forEach(function(paciente){
            var tdNome = paciente.querySelector(".info-nome");
            var nome = tdNome.textContent;
            var expressao = new RegExp(inputValue,"i");
            if( !expressao.test(nome) ){
                paciente.classList.add("invisivel");
            }else{
                paciente.classList.remove("invisivel");
            }
        });
    }else{
        pacientes.forEach(function(paciente){
            paciente.classList.remove("invisivel");
        });
    }

Ao passar para uma variável o valor do input de pesquisa, vc consegue utilizá-la dentro do escopo da função de callback do forEach.

O Guilherme está correto! Tive a mesma dúvida e o Pedro Avila me explicou em mais detalhes aqui no fórum, segue o link do post:

https://cursos.alura.com.br/forum/topico-usar-logica-com-foreach-para-implementar-filtro-nao-esta-funcionando-47632

Perfeito Guilherme.