I'm trying to grab an element from page and add an addEventHandler to it. Element (link with class .catalog__link) was dynamically created in another external function when the page was loaded using insertAdjacentHTML. I invoke them both in third js file via import keyword. Everything loads perfectly on the page, the elements are created for me, but I can’t grab them from another function connected to the page. Here’s examples of codes. I have two external function, combined in one js file and simple html page
This is fillCatalog.js (First file)
const row = document.querySelector('.catalog__row');
export const fill = function (brand) {
fetch(`./data/${brand}.json`)
.then(function (response) {
return response.json();
})
.then(function (data) {
let products = [...data.products];
products.forEach(product => {
row.insertAdjacentHTML(
'afterbegin',
` <a class="catalog__link" href="#" >
<div class="catalog__product">
<div class="catalog__product-img">
<img class="catalog__productImg" src=${product['img-src']} alt="" srcset="" />
</div>
<h3 class="catalog__product-model">${product['model']}</h3>
<p class="catalog__product-brand">${product['brand']}</p>
<span class="catalog__product-price">${product['price']}</span>
</div></a>`
);
});
});
};
This is productSave.js (Second file)
class Product {
constructor(cardImg, cardName, cardBrand = '', cardPrice) {
this.cardImg = cardImg;
this.cardName = cardName;
this.cardBrand = cardBrand;
this.cardPrice = cardPrice;
}
}
const links = document.querySelectorAll('.catalog__link');
export const productSave = function () {
window.addEventListener('DOMContentLoaded', () => {
console.log(links);
links.forEach(link => {
link.addEventListener('click', e => {
productItem = link.querySelector('.catalog__product');
const newProduct = new Product(
productItem.querySelector('catalog__productImg').src,
productItem.querySelector('.catalog__product-model').textContent,
productItem.querySelector('.catalog__product-brand').textContent,
productItem
.querySelector('.catalog__product-price-price')
.textContent.replace(/\D/g, '')
);
localStorage.setItem('newCard', JSON.stringify(newProduct));
console.log(card.querySelector('.card__name').textContent);
});
});
});
};
This is third file where I invoke external function
loadContent.js
import { fill } from './fillCatalog.js';
import { productSave } from './productSave.js';
fill('jordans');
productSave();
Simple HTML
<html lang="ru">
<head>
<!--=include head.html-->
</style>
</head>
<body>
<div class="catalog">
<div class="catalog__content">
<div class="catalog__row"></div>
</div>
</div>
</body>
<script type="module" src="../js/goodscart.js"></script>
<script type="module" src="../js/loadContent.js"></script>
</html>
I've tried use beforeend afterent and etc. Tried also use getElementsByTag, it returns empty HtmlCollection[]. After insertAdjacentHTML, can't select like usually this links.
Could anyone help me please with this issue? I can't find solution for that. Thank you
You need to define
linksinside the function to avoid it being initialized before the elements are rendered.Initialization of
linksHandling the
fillPromiseFuthermore there is a fetch reuqest inside
fillwhich returned a promise.Then you can properly chain the call to the following function like so
Workaround to detect classes in dom
You can also implement a detector that waits for at least one link to be rendered. This
Promisewould resolve after at least1item withcatalog__linkcan be found. Then you can chain your logic with.then(...). This one also includes a timeout of 10 seconds which executes.catch(...)(if present otherwise throws) if the element was not found in time.