- У меня проблемы с захватом динамически созданных элементов DOM и
- Я не знаю, где должно происходить последующее делегирование события клика (то есть в моем основном файле .js или внутри класса пользовательского интерфейса).
Этот проект объектно-ориентированного обучения отправляет асинхронные HTTP-запросы с помощью выборки в API Punk и извлекает список пива на основе поискового запроса пользователя. Вывод не является жестко запрограммированным, а innerHTML списка создается динамически из данных API внутри класса с именем UI.
В app.js я обрабатываю обещания и использую ui.paint() для отображения пива на странице.
У каждого пива есть кнопка «купить», которая также создается динамически.
Я хочу захватить все кнопки, прокрутить их, прикрепить событие щелчка.
Я пробовал:
захват кнопок в app.js с помощью queryselectorAll - не работает, возвращает пустой список узлов - этот селектор должен быть поднят, и на момент вызова кнопки явно еще не существуют - ЕСТЬ КАКОЙ-ТО АСИНХРОННЫЙ СПОСОБ решить это и дождаться возврата данных API и создания новых элементов? (примечание: когда у меня есть список сортов пива, я могу получить полный список узлов с помощью querySelectorAll в консоли браузера...)
Я также попытался обернуть queryselectorAll внутри функции и вызвать эту функцию внутри функции события click, которая обрабатывает обещания. Это тоже не сработало.
Я попытался поместить событие в app.js, а также в класс прототипа пользовательского интерфейса (который выглядел более аккуратно), но ни один из них не работает.
app JS
const ui = new UI();
document.getElementById('submit-button- name').addEventListener('click', (e) => {
e.preventDefault();
const newBeer = new Beer();
newBeer.getByName()
.then(beerResult => {
ui.paint(beerResult);
})
.catch(err => {
console.log(err)
});
});
const buyBtns = document.querySelectorAll('#buy-btn');
buyBtns.forEach((buyBtn) => {
buyBtn.addEventListener('click', (e) => {
ui.addToCart(e)
});
});
then here is the UI class, trying to pick up the event (I'm trying to grab the button that's in the last <a> tag of the innerHTML and push it in a cart array which I would later display on a separate page).
class UI {
constructor() {
this.productRow = document.getElementById('products-row');
}
paint(beerResult) {
let output = '';
beerResult.forEach(beer => {
output +=
`<div class="card">
<img id="beer-card-img" src="${beer.image_url}" alt="beer-image" class="card-image-top">
<div class="card-body">
<h5 class="card-title">${beer.name}</h5>
<h6 class="tagline">${beer.tagline}.</h6>
<p id="description" class="card-text">${beer.description}</p>
<p id="abv" class="card-text">ABV: ${beer.abv}</p>
<p id="ibu" class="card-text">IBU: ${beer.ibu}</p>
<p id="ph" class="card-text">PH: ${beer.ph}</p>
<p id="first-brewed" class="card-text">First brewed: ${beer.first_brewed}</p>
<a href="#" class="btn btn-outline-dark btn-sm">See details</a>
<a href="#" id="buy-btn" class="btn btn-danger btn-sm">Buy</a>
</div>
</div>`
});
// console.log(output);
this.productRow.innerHTML = output;
}
addToCart(e) {
let cart = [];
if (e.target.parentElement.parentElement.classList.contains('card')) {
cart.push(e.target.parentElement.parentElement)
}
console.log(cart);
}
}
Сейчас ничего не происходит, когда я нажимаю «Купить». Я хочу, чтобы пиво помещалось в массив (как объекты) для последующего отображения на отдельной странице.
Спасибо за терпение, время и советы!