0

I am creating a project that when I click a certain category card I get the id of that category and redirect to movies screen.

I am aware that the row.eventlistener() in index.js it will be executed before the elements are rendered and that is why it does not pick the id. How should I add the event listener to each newly rendered item before adding it to the container so that I can get the id for each category card.

index.js

async function getCategories() {
  let url = 'http://localhost:8080/movieCategories';
  try {
    let res = await fetch(url);
    return await res.json();
  } catch (error) {
    console.log(error);
  }
}


async function renderCategories() {
  let categories = await getCategories();
  let html = '';
  categories.forEach(category => {


    let htmlSegment = `
            <div class="category-card" id=${category.id}>
            <img src="./assets/images/sci-fi.jpg" alt="" class="card-img">
            <div class="name">${category.name}</div>
          </div>
        `;
    html += htmlSegment;
  });
  let container = document.querySelector('.category-grid');
  container.innerHTML = html;
}

 renderCategories();


document.querySelectorAll('div.category-card').forEach(row=>{
  row.addEventListener('click',event=>{
    console.log('Category clicked', event.currentTarget.id)
    window.location= 'movies.html?categoryId=' +event.currentTarget.id;
  });

});

index.html

<section class="category" >
  <h2 class="section-heading">Category</h2>
  <div class="category-grid">
  </div>
</section>
  • I have tried to put the event listener logic inside but still did not work .In which place exactly inside and how ? – User G Amsterdam Jun 02 '22 at 13:31
  • So odd you are reinventing html anchors – epascarello Jun 02 '22 at 13:31
  • The OP wants to register a single event handler exactly once at the root node (which is ... `document.querySelector('.category-grid')`) and then make use of [event delegation](https://davidwalsh.name/event-delegate). Any content inside of the root node can be removed / replaced / inserted at will without any additional event listening tasks. – Peter Seliger Jun 02 '22 at 13:45

3 Answers3

0

You are not awaiting the call to renderCategories, move your event listener logic inside the renderCategories method OR You could use an immediately invoked async function expression or IIAFE for short, more about this here immediately-invoked-async-function-expression:

    (async () => {
        await renderCategories();
        document.querySelectorAll('div.category-card').forEach(row => {
           row.addEventListener('click', event => {
               console.log('Category clicked', event.currentTarget.id)
               window.location= 'movies.html?categoryId=' +event.currentTarget.id;
           });
        });
    })();
Ryan Wilson
  • 10,223
  • 2
  • 21
  • 40
0

You could also just add the event on the div itself directly when you create it and pass the id or whatever you want.

<div class="category-card" id=${category.id} onclick="onCatClick(${category.id})">

After this, you can move your logic inside a top level onCatClick function.

function onCatClick(id) {
    console.log('Category clicked', id)
    window.location= 'movies.html?categoryId=' + id;
}

This is if your styling/layout doesn't allow you to use an anchor element. Otherwise, you could simply replace the div with an anchor element:

<a href="movies.html?categoryId=${id}"></a>
-1

try:

async function getCategories() {
  let url = 'http://localhost:8080/movieCategories';
  try {
    let res = await fetch(url);
    return await res.json();
  } catch (error) {
    console.log(error);
  }
}


async function renderCategories() {
  let categories = await getCategories();
  let html = '';
  categories.forEach(category => {


    let htmlSegment = `
            <div class="category-card" id=${category.id}>
            <img src="./assets/images/sci-fi.jpg" alt="" class="card-img">
            <div class="name">${category.name}</div>
          </div>
        `;
    html += htmlSegment;
  });
  let container = document.querySelector('.category-grid');
  container.innerHTML = html;
}
 //es8
await renderCategories();

// fix timeout async render element
setTimeout(() => {
  document.querySelectorAll('div.category-card').forEach(row=>{
    row.addEventListener('click',event=>{
      console.log('Category clicked', event.currentTarget.id)
      window.location= 'movies.html?categoryId=' +event.currentTarget.id;
    });
  })
});
Tachibana Shin
  • 2,605
  • 1
  • 5
  • 9