0

I'm new to JavaScript and looking for a simple way to pass a parameter to an event listener. I'm dynamically creating a bunch of divs from an API call (which returns a list of data objects to display as divs) and want to make each one clickable. My problem is that I'm unable to figure out how to pass in a parameter upon clicking the element since it is out of scope. I simply want the "load_email" function I've written to have access to data[i].id. Here is what I have so far:

    // Put response into json form
    .then(response => response.json())
    .then(data => {
        // Log data to the console, create email items
        console.log(data);
        for (var i = 0; i < data.length; i++) {
          const element = document.createElement('div');
          element.classList.add('box');
          element.classList.add('px-2');
          element.classList.add('py-1');
          element.innerHTML = `
            <div class="row">
              <div class="col-3">
                <strong>${data[i].sender}</strong>
              </div>
              <div class="col-5">
                ${data[i].subject}
              </div>
              <div class="col-4 text-right">
                ${data[i].timestamp}
              </div>
            </div>
          `;
          if (data[i].read == true) {
            element.classList.add('white');
          } else{
            element.classList.add('grey');
          }
          element.addEventListener('click', () => load_email(data[i].id); **//THIS IS WHERE IM STRUGGLING**
          document.querySelector('#emails-view').append(element);
        }
    });

function load_email(id){
  document.querySelector('#emails-view').style.display = 'none';
  document.querySelector('#compose-view').style.display = 'none';
  document.querySelector('#open-mail-view').style.display= 'block';

  console.log(`load email id ${id}`)
}
  • What exactly seems to be the problem? What error are you receiving? – jaimish11 Aug 03 '20 at 16:44
  • Use `for (let i = 0; i < data.length; i++)` - it's `let` instead of `var`. See also [Javascript infamous Loop issue?](https://stackoverflow.com/q/1451009) – VLAZ Aug 03 '20 at 16:47
  • By the way, set the id somewhere in the element and add the click event listener to `#emails-view` to share one single listener. The event object includes the target element which you can get back the id. – TimTIM Wong Aug 03 '20 at 16:49
  • rather than looping like `for (var i = 0; i < data.length; i++) {` and then getting each data piece, `data[i]`, you can just loop directly over the objects, `for (let obj of data)` and then you have access to `obj` inside any clojures defined in that loop – TKoL Aug 03 '20 at 16:56

1 Answers1

3
const j = i;
element.addEventListener('click', () => load_email(data[j].id);

Note that var is function scoped, while let and const are block scoped.

TimTIM Wong
  • 788
  • 5
  • 16