Estoy creando un proyecto que cuando hago clic en una determinada tarjeta de categoría obtengo la identificación de esa categoría y redirijo a la pantalla de películas.
Soy consciente de que row.eventlistener() en index.js se ejecutará antes de que se representen los elementos y es por eso que no selecciona la identificación. ¿Cómo debo agregar el detector de eventos a cada elemento recién renderizado antes de agregarlo al contenedor para poder obtener la identificación de cada tarjeta de categoría?
índice.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; }); });índice.html
<section class="category" > <h2 class="section-heading">Category</h2> <div class="category-grid"> </div> </section>No está esperando la llamada a renderCategories , mueva su lógica de escucha de eventos dentro del método renderCategories O puede usar una expresión de función asíncrona invocada inmediatamente o IIAFE para abreviar, más sobre esto aquí expresión-función-asíncrona-invocada-inmediatamente :
(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; }); }); })();También puede simplemente agregar el evento en el div directamente cuando lo crea y pasar la identificación o lo que quiera.
<div class="category-card" id=${category.id} onclick="onCatClick(${category.id})"> Después de esto, puede mover su lógica dentro de una función onCatClick de nivel superior.
function onCatClick(id) { console.log('Category clicked', id) window.location= 'movies.html?categoryId=' + id; }Esto es si su estilo/diseño no le permite usar un elemento de anclaje. De lo contrario, simplemente podría reemplazar el div con un elemento de anclaje:
<a href="movies.html?categoryId=${id}"></a>probar:
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; }); }) });