Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

167
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!