Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

163
Visualizações
Adding Click Event Listeners During Iteration?

I'm trying to add a click event listener to a bunch of newly created divs in a for loop. The issue I'm having is that only the last div keeps its event listener. I've read up about closures and read several other posts and questions and their answers, and as far as I can tell I have it set up correctly. But it still isn't working for me. Only the final div to be iterated is receiving the event listener.

function edit_entry(k) {
    wrd_input.value = k;
    def_input.value = lexicon[k][1];
    wrd_input.onkeyup();

    delete lexicon[k];
    rewrite_entries();
}

function rewrite_entries(keys = null) {
    if (keys === null) { keys = []; }
    let sorted_keys = sort_lex_keys();
    lex_body.style.color = 'rgb(200, 200, 200)';
    lex_body.innerHTML = '';

    sorted_keys.forEach((key) => {
        if (!keys.length || keys.includes(key)) {
        lex_body.innerHTML += 
        `<div class='lex-entry' id=${key}><i>${key}</i>\n<p class='pronunciation'>${lexicon[key][0]}</p>${lexicon[key][1]}</div>\n`;
        let entry = document.getElementById(key)
        entry.addEventListener('click', edit_entry.bind(this, key) );
        }
    });
}

Current state of the relevant code above. If somebody knows the issue, it'd be very helpful. If it's relevant, this code is running via Electron (17.0.0).

An attempted solution, using an anonymous arrow function instead of a bind:

entry.addEventListener('click', () => edit_entry(key) );

yields the same result.


Update: Changing the .innerHTML attribute of something apparently strips all event listeners. So the solution was simply to create the element completely in js, add it to the container, and then add the listener. This change to the forEach loop solves the problem:

    sorted_keys.forEach((key) => {
        if (!keys.length || keys.includes(key)) {
            let entry = document.createElement('div');
            entry.className = 'lex-entry';
            
            let word = document.createElement('p');
            word.appendChild( document.createTextNode(key) );
            word.style.fontStyle = 'italic';
            
            let pron = document.createElement('p');
            pron.className = 'pronunciation';
            pron.appendChild( document.createTextNode(lexicon[key][0]) );
            
            let defn = document.createTextNode(lexicon[key][1]);
            
            entry.append(word, pron, defn);
            entry.addEventListener('click', () => edit_entry(key) );

            lex_body.appendChild(entry);
about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

So a few things crosses my mind:

Firstly, edit_entry.bind(this, key);: Are you certain this is pointing to what you want? It should be pointing to the window object. Also, is there any reason to bind context for that particular function?

Secondly innerHTML: Generally it's discouraged to use innerHTML directly. I don't know how/when the browser layouts changes to innerHTML, the div might not be on the page when you call getElementById. As an alternative, you could try document.createElement("div"), set its properties accordingly and finally append it to lex_body.

Edit

From mdn:

Please note that using innerHTML to append html elements (e.g. el.innerHTML += "link") will result in the removal of any previously set event listeners. That is, after you append any HTML element that way you won't be able to listen to the previously set event listeners.

about 4 years ago · Juan Pablo Isaza Relatório

0

I think that binding the function every time with this is overriding the binding every time, that should be the reason that you are only getting the last one's event.

Inside of the forEach lambda, the this keyword refers to the internal class that is calling the forEach not your rewrite_entries function. Try not binding the call, like so:

entry.addEventListener('click', () => edit_entry(key) );
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda