1
resposta

Problema com o botão remover

Oi pessoal,

Estou com um problema no botão de remover a linha. Ele está identificando o click, já que o event.preventDefault() surtiu efeito, mas ele parece não estar identificando que o "this" se refere a ao objeto $(".botao-remover).

Javascript:

var tempoInicial = $("#tempo-digitacao").text();
var campo = $(".campo-digitacao");

$( () => {
    atualizaTamanhoFrase();
    inicializaContadores();
    inicializaCronometro();
    $("#botao-reiniciar").click(reiniciaJogo);
    inicializaMarcadores();
})

function atualizaTamanhoFrase() {
    var frase = $(".frase").text();
    var numPalavras = frase.split(" ").length;
    var tamanhoFrase = $("#tamanho-frase")
    tamanhoFrase.text(numPalavras);
}

function inicializaContadores() {
    campo.on("input",() => {
        var conteudo = campo.val();
        var qtdPalavras = conteudo.split(/\S+/).length -1;
        $("#contador-palavras").text(qtdPalavras)
        $("#contador-caracteres").text(conteudo.length)
    });
}


function inicializaCronometro() {
    var tempoRestante = $("#tempo-digitacao").text();
    campo.one("focus", () => {
    var cronometroID = setInterval(() =>{
        tempoRestante -= 1;
        $("#tempo-digitacao").text(tempoRestante)
        if(tempoRestante <1){
            clearInterval(cronometroID);
            finalizaJogo();
        }
    },1000)
})
}

function finalizaJogo(){
    campo.attr("disabled", true);
    campo.toggleClass("campo-desativado")
    inserePlacar();
}

function inicializaMarcadores(){
    var frase = $(".frase").text();
    campo.on("input", () => {
        var digitado = campo.val();
        var comparavel = frase.substr(0,digitado.length)
        if(digitado == comparavel){
            campo.addClass("borda-verde");
            campo.removeClass("borda-vermelha")
        } else {
            campo.addClass("borda-vermelha");
            campo.removeClass("borda-verde")
        }
    });
}

function inserePlacar(){
    var corpoTabela = $(".placar").find("tbody");
    var usuario = "Cassiano";
    var numPalavras = $("#contador-palavras").text();
    var botaoRemover = "<a href='#'><i class='small material-icons'>delete</i></a>"

    var linha = `<tr>
                    <td>` + usuario + `</td>
                    <td>` + numPalavras + `</td>
                    <td>` + botaoRemover + `</td>
                </tr>`;

    corpoTabela.append(linha);
}

$(".botao-remover").click( (event) => {
    console.log(this)
    event.preventDefault();
    $(this).parent().parent().remove();
});


function reiniciaJogo() {
    campo.attr("disabled",false);
    campo.val("");
    $("#contador-palavras").text("0");
    $("#contador-caracteres").text("0");
    $("#tempo-digitacao").text(tempoInicial);
    inicializaCronometro();
    campo.toggleClass("campo-desativado");
    campo.removeClass("borda-vermelha")
    campo.removeClass("borda-verde")
}

HTML:

        <section class="placar">
            <h3 class="center">Placar</h3>
            <table class="centered bordered">
                <thead>
                    <tr>
                        <th>Nome</th>
                        <th>No. de palavras</th>
                        <th>Remover</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>Cassiano</td>
                        <td>10</td>
                        <td>
                            <a href="#" class="botao-remover">
                                <i class="small material-icons">delete</i>
                            </a>
                        </td>
                    </tr>

                </tbody>
            </table>
        </section>
1 resposta

Oi Cassiano!

Primeiro vamos entender porque a função

$(".botao-remover").click( (event) => {
    console.log(this)
    event.preventDefault();
    $(this).parent().parent().remove();
});

Não funciona do jeito que você deseja. O console.log(this) deve estar te mostrando um objeto Window, que é o objeto global da janela do navegador. Isto pode parecer um bug, mas na verdade é o comportamento esperado. Apesar de arrow functions e funções normais parecerem a mesma coisa, elas funcionam de um jeito diferente em relação ao uso do this.

Basicamente, nas arrow functions o this se refere ao escopo léxico no qual foi declarado. Como o escopo mais próximo da declaração da sua função é o global, o this da sua função de deletar é o objeto global Window. Se você converter sua arrow function numa função normal, seu código terá o comportamento esperado, pois o this agora será o objeto que chamou a função, neste caso o botão remover.

$(".botao-remover").click( function (event)  {
    console.log(this)
    event.preventDefault();
    $(this).parent().parent().remove();
});

Para entender melhor sobre as diferenças dos tipos de função, recomendo a leitura deste artigo sobre arrow functions e este video sobre o funcionamento do this.

Se você quiser manter o uso da arrow function, uma solução é substituir o this pelo currentTarget do parâmetro event, da seguinte forma:

$('.botao-remover').click((event) => {
  event.preventDefault();
  $(event.currentTarget).parent().parent().remove();
});

O this causa muitos problemas devido ao seu comportamento dinâmico e essa última solução serve tanto para arrow functions tanto para funções normais, pois não depende mais do this.

Agora, o clique no botão irá funcionar corretamente, mas infelizmente os botões criados dinâmicamente no placar não funcionarão. Você precisa achar uma forma de associar a função criada para remover ao clique do botão criado dinamicamente. Fica aí o desafio!

Espero ter ajudado. Se tiver você travar no desafio, comenta aqui! Bons estudos!