Ygg
Ygg2y ago

✅ – ✅ – ✅ – Ygg – 21-49 Oct 31

Hello everyone I'm making a Pokedex using PokeAPI I'm trying to add addEventListener('click', ...) to every Pokémon element so I can use it to open a Modal with the detailed Pokémon info As I'm fetching info from the API, I'm getting errors. I can't seem to find a way to add those eventListeners after the fetch I googled it for hours and was reading about callbacks and async/await, but coudn't make it work... I even tried to use a global "reader" to see if any fetch is completed in the page and managed to console.log every entry after they finish fetch, unsuccesful The code in Screenshot is pretty much all JS code I have Any help?
9 Replies
Ygg
Ygg2y ago
Errors like empty string or the Click effect simply not working Empty arrays happens when I use querySelector, nothing happens when I use getElementByClassName Sorry, I'll add the code again, it's a really simple for loop using the pokeCardList Sorry about the delay and about the missing code, I tried to use that
function addListeners() {
for (var i = 0; i < pokeCardList.length; i++) {
pokeCardList[i].addEventListener("click", () => {
console.log("click");
});
}
}
function addListeners() {
for (var i = 0; i < pokeCardList.length; i++) {
pokeCardList[i].addEventListener("click", () => {
console.log("click");
});
}
}
I also removed de dot at getElementsByClassName(".pokemon"); It was an attempt to make it work with querySelector The loop you're talking about is the .map at loadPokeCards? I'm failing to see how can I add the event inside of it while calling it I know that this is really basic but is so abstract that my head is just spinnig right now lily weird to be able to make this easily with React but when I go to the fundamentals I see I'm just a lil potato I'll read it carefuly
liil'boo
liil'boo2y ago
export function createElement(type, options = {}) {
const element = document.createElement(type); Object.entries(options).forEach(
([key, value]) => {
if (key === "class"){
element.classList.add(value) return }
if (key === "dataset"){
Object.entries(value).forEach(([dataKey, dataValue]) => { element.dataset[dataKey] = dataValue }) return } if (key === "text") { element.textContent = value return } element.setAttribute(key, value) }) return element}
export function createElement(type, options = {}) {
const element = document.createElement(type); Object.entries(options).forEach(
([key, value]) => {
if (key === "class"){
element.classList.add(value) return }
if (key === "dataset"){
Object.entries(value).forEach(([dataKey, dataValue]) => { element.dataset[dataKey] = dataValue }) return } if (key === "text") { element.textContent = value return } element.setAttribute(key, value) }) return element}
Usage
const element = createElement("button", { class: "btn", text: "New", dataset: { test: true }, id: "new", "data-hi": "Yes",})
const element = createElement("button", { class: "btn", text: "New", dataset: { test: true }, id: "new", "data-hi": "Yes",})
I trust you to figure things out, hope it helps
Ygg
Ygg2y ago
Sorry, didn't saw your message before trying out today nervousr did it by myself today and achieve the same UI I had before with this
function drawPokeCard(pokemon) {
const { name, types, id, mainType } = pokemon;
const imgURL =
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/";

// create ui
const pokeCard = document.createElement("article");
const info = document.createElement("div");
const number = document.createElement("p");
const pokeName = document.createElement("p");
const typesContainer = document.createElement("div");
const type = document.createElement("p");
const imgContainer = document.createElement("div");
const img = document.createElement("img");

// add classes
pokeCard.classList.add("pokemon", mainType);
info.classList.add("info");
number.classList.add("number");
pokeName.classList.add("name");
typesContainer.classList.add("types");
type.classList.add("type");
imgContainer.classList.add("image");

// add content
number.innerText = "#" + lpad(id, 3, 0);
pokeName.innerText = name;
img.src = imgURL + id + ".png";
img.alt = name;

// draw the card
pokemonList.append(pokeCard);
pokeCard.append(info, imgContainer);
info.append(number, pokeName, typesContainer);
imgContainer.append(img);

// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});

// add types
typesContainer.innerHTML = `${types
.map((type) => `<p class=${type}>${type}</p>`)
.join("")}`;
}
function drawPokeCard(pokemon) {
const { name, types, id, mainType } = pokemon;
const imgURL =
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/";

// create ui
const pokeCard = document.createElement("article");
const info = document.createElement("div");
const number = document.createElement("p");
const pokeName = document.createElement("p");
const typesContainer = document.createElement("div");
const type = document.createElement("p");
const imgContainer = document.createElement("div");
const img = document.createElement("img");

// add classes
pokeCard.classList.add("pokemon", mainType);
info.classList.add("info");
number.classList.add("number");
pokeName.classList.add("name");
typesContainer.classList.add("types");
type.classList.add("type");
imgContainer.classList.add("image");

// add content
number.innerText = "#" + lpad(id, 3, 0);
pokeName.innerText = name;
img.src = imgURL + id + ".png";
img.alt = name;

// draw the card
pokemonList.append(pokeCard);
pokeCard.append(info, imgContainer);
info.append(number, pokeName, typesContainer);
imgContainer.append(img);

// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});

// add types
typesContainer.innerHTML = `${types
.map((type) => `<p class=${type}>${type}</p>`)
.join("")}`;
}
The event listener finally worked as I wanted
// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});
// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});
But then comes the question... is there a better way to do it rather than doing it step by step? I could try to make a function to create new elements like @Liil' Boo sugested, but is it the best way? I'm only asking because I had experience with React before and doing the opposite way going back to JS make it looks like I'm typing a lot Wich is not a big deal, just wondering how I could improve this also, I couldn't figure out how to make the types without innerHTML, is this okay?
// add types
typesContainer.innerHTML = `${types
.map((type) => `<p class=${type}>${type}</p>`)
.join("")}`;
// add types
typesContainer.innerHTML = `${types
.map((type) => `<p class=${type}>${type}</p>`)
.join("")}`;
liil'boo
liil'boo2y ago
It's a utility function I'll see your thing and propose something in about an hour (small refactoring suggestion for readibility - I'm not questioning what you are doing) This is what it would look like with the suggestion, it would be more maintainable That's all for me. Good luck
function drawPokeCard(pokemon) {
const { name, types, id, mainType } = pokemon;
const imgURL =
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/";

// create ui
const pokeCard = createElement("article", {
class : `pokemon ${mainType}`
});
const info = createElement("div", {
class: "info"
});
const number = createElement("p", {
class: "number"
});
const pokeName = createElement("p", {
class:"name"
});
const typesContainer = createElement("div", {
class: "types"
});
const type = createElement("p", {
type
});
const imgContainer = createElement("div", {
class: "image"
});
const img = createElement("img", {
src: `${imgURL}${id}.png`,
alt: "name"
})

//add content //code

// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});
function drawPokeCard(pokemon) {
const { name, types, id, mainType } = pokemon;
const imgURL =
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/";

// create ui
const pokeCard = createElement("article", {
class : `pokemon ${mainType}`
});
const info = createElement("div", {
class: "info"
});
const number = createElement("p", {
class: "number"
});
const pokeName = createElement("p", {
class:"name"
});
const typesContainer = createElement("div", {
class: "types"
});
const type = createElement("p", {
type
});
const imgContainer = createElement("div", {
class: "image"
});
const img = createElement("img", {
src: `${imgURL}${id}.png`,
alt: "name"
})

//add content //code

// add event listener
pokeCard.addEventListener("click", () => {
console.log("click");
});
Ygg
Ygg2y ago
Thank you very much for your time and Subone :3
reactibot
reactibot2y ago
This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1036758918820544592
reactibot
reactibot2y ago
This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1036758918820544592 This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1036758918820544592
Ygg
Ygg2y ago
Damn, not a question but I realized that I could just create the <article> with .createElement and then add the rest with .innerHTML Much easier to work than trying to abstract everything bighmm for the sake of reference in case anyone come here, it looks like this now 😄
// draw poke cards at main page
function drawPokeCard(pokemon) {
const { name, imgURL, types, id, mainType } = pokemon;
const pokeNumber = "#" + lpad(id, 3, 0);

// create ui
const pokeCard = document.createElement("article");

// add classes
pokeCard.classList.add("pokemon", mainType);

// draw the card
pokemonList.append(pokeCard);
pokeCard.innerHTML = `
<div class="info">
<p class="number">${pokeNumber}</p>
<p class="name">${name}</p>
<div class="types">
${types.map((type) => `<p class=${type}>${type}</p>`).join("")}
</div>
</div>
<div class="image">
<img
src=${imgURL}
alt=${name}
/>
</div>`;

// add event listener
pokeCard.addEventListener("click", () => {
drawModalWithPokemon(pokemon);

toggleModal();
});
}
// draw poke cards at main page
function drawPokeCard(pokemon) {
const { name, imgURL, types, id, mainType } = pokemon;
const pokeNumber = "#" + lpad(id, 3, 0);

// create ui
const pokeCard = document.createElement("article");

// add classes
pokeCard.classList.add("pokemon", mainType);

// draw the card
pokemonList.append(pokeCard);
pokeCard.innerHTML = `
<div class="info">
<p class="number">${pokeNumber}</p>
<p class="name">${name}</p>
<div class="types">
${types.map((type) => `<p class=${type}>${type}</p>`).join("")}
</div>
</div>
<div class="image">
<img
src=${imgURL}
alt=${name}
/>
</div>`;

// add event listener
pokeCard.addEventListener("click", () => {
drawModalWithPokemon(pokemon);

toggleModal();
});
}
reactibot
reactibot2y ago
This thread hasn’t had any activity in 12 hours, so it’s now locked. Threads are closed automatically after 12 hours. If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1036758918820544592