Use id from Template strings item - javascript

i'm having a trouble using the id from a template string item
const elementoParaInserirJogosNaLista = document.getElementById("listaJogos");
function exibirJogosNaTela(listaDeJogos) {
elementoParaInserirJogosNaLista.innerHTML = "";
listaDeJogos.forEach((jogo) => {
elementoParaInserirJogosNaLista.innerHTML += `
<div class="jogo">
<a href="paginajogo.html">
<img class="jogo__imagem" src="${jogo.imagem}" alt="${jogo.titulo}" />
</a>
<h2 class="jogo__titulo">${jogo.titulo}</h2>
<p class="jogo__preco" id="preco">R$${jogo.preco}<a ><img class="jogo__carrinho" id="addCarrinho" src="./images/addcart.png" alt="Adicionar ao carrinho"/></p><a/>
</div>
`;
});
}
i've tried to use the id "addCarrinho" and nothing happens
i'm newb on developing
const botoesAddCarrinho = [];
botoesAddCarrinho = document.querySelectorAll(".jogo__carrinho");
botoesAddCarrinho.forEach((evento) =>
evento.addEventListener("click", addNoCarrinho)
);
function addNoCarrinho () {
console.log('ok')
}
i've changed the selector to by the class, but nothings happens, is like the nothing was selected
i'm using the exibirNaTela on the fetch with the json
let jogos = [];
const endpointDaAPI ="jogos.json"
getBuscarJogosDaAPI();
async function getBuscarJogosDaAPI() {
const respost = await fetch(endpointDaAPI);
jogos = await respost.json();
exibirJogosNaTela(jogos.jogos);
}

Related

Event listener not working after elements are rendered in the dom

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>
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:
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;
});
});
})();
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;
});
})
});

Cannot pass Object as param to onClick while iterating with innerHTML

I am currently iterating through a list of movies and want to be able to make each element clickable and pass their respective movie information to the click event.
Here is how I iterate through my data. I want to be able to pass the movie information to the click event so that when I click on a movie, I can display its information :
const APIKEY = 'api_key=blabla....';
const BASE_URL = 'https://api.themoviedb.org/3';
const API_URL = BASE_URL + '/discover/movie?sort_by=popularity.desc&' + APIKEY;
const IMG_URL = 'https://image.tmdb.org/t/p/w500';
const SEARCH_URL = BASE_URL + '/search/movie?' + APIKEY;
const main = document.getElementById('main')
const form = document.getElementById('form')
const search = document.getElementById('search')
getMovies(API_URL);
function getMovies(url) {
fetch(url).then(res => res.json()).then(data => {
showMovies(data.results);
console.log(data.results)
})
}
function showMovies(data){
main.innerText = '';
data.forEach((movie, index) => {
let {title, poster_path, release_date, overview} = movie;
let movieEl = document.createElement('div');
movieEl.classList.add('movie');
movieEl.innerHTML = `
<div onclick="showMovieInfo(${movie[index]})" style="cursor: pointer;">
<img src="${IMG_URL + poster_path}" alt="${title}">
<div class="movie-info">
<h3>${title}</h3>
<span>${release_date.slice(0,4)}</span>
</div>
<div class="overview">
${overview}
</div>
</div>
`
main.appendChild(movieEl)
})
}
For Now i just want to be able to console.log the movie info for each
function showMovieInfo(movie) {
console.log(movie)
}
Currently I get this error when I click on an element: Uncaught SyntaxError: Unexpected identifier
Do you guys know what I could do to make it work?
The problem here ist that the "movie" object don´t exist in the "innerHTML" context. One Solution would be to serialise the movie Object or pass the Index and than get the Object from the data Array.
You can´t pass an Object to innerHTML so you have to pass a Primitive values like string or number.
const main = document.getElementById('main');
const IMG_URL = "/"
const data = [{title: "New Movie", poster_path:"",release_date:"2021-10-31", overview:"nice movie" }];
function showMovieInfo(movieId){
console.log(data[movieId])
}
function showMovies(data){
main.innerText = '';
data.forEach((movie, index) => {
let {title, poster_path, release_date, overview} = movie;
let movieEl = document.createElement('div');
movieEl.classList.add('movie');
movieEl.innerHTML = `
<div onclick="showMovieInfo(${index})" style="cursor: pointer;">
<img src="${IMG_URL + poster_path}" alt="${title}">
<div class="movie-info">
<h3>${title}</h3>
<span>${release_date.slice(0,4)}</span>
</div>
<div class="overview">
${overview}
</div>
</div>
`
main.appendChild(movieEl)
})
}
showMovies(data);
<div id="main">
</div>

Using fetch results as function parameters

i have fetchTeam(teamName) function which gets an array of players and displays them in HTML. and another function that takes a player name as a parameter and displays the player stats. Something like this....
let result = document.getElementById("result");
let teamName;
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
const response = await fetch(`http://localhost:3000/${teamName}`);
const data = await response.json();
let team = data.teamStats;
let players = data.playerStats;
const teamName = team[0].Name;
const logo = team[0].Logo;
const WL = team[0].WL;
result.innerHTML = `
<br><div class="top">
<h3>${teamName}</h3>
<h4>Win / Loss: ${WL}</h4>
<img src=${logo}></div>
<div class="flex-container">
<div class="flex-child">
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")> ${players[0][0].Player} </button> ...
`
That all works fine except the onclick fetchPlayer function at the bottom.... Heres the code for that:
const results = document.getElementById("results");
const fetchPlayer = async (player) => {
const response = await fetch(`https://get-player.herokuapp.com/${player}`);
const data = await response.json();
results.innerHTML = `
<br>
<div class="layout">
<div class="child"><img src="${data.sprite}[0]"><br>${data.mons[0]}</div>
`
As you can see, i want to display the team members and then clicking on a member name will show their stats.
edit: format
There are several issues in your code.
First, you redeclare teamName in your fetchTeam function. That cannot work.
const fetchTeam = async (teamName) => {
teamName = document.getElementById("teamName").value;
...
const teamName = team[0].Name;
}
Second, your button syntax is incorrect :
<button class='name' onclick="fetchPlayer("${players[0][0].Player}")>
should be
<button class='name' onclick="fetchPlayer('${players[0][0].Player}')">
Third, as pointed out in this answer, in your fetchPlayer function
<img src="${data.sprite}[0]"> should be <img src="${data.sprite[0]}">
In the fetchPlayer function,
Change <img src="${data.sprite}[0]"> to <img src="${data.sprite[0]}">

Can't get field from Firebase Firestore

I've tried to retrieve a saved picture URL from Firebase Firestore, but I'm keep getting this error:
Uncaught (in promise) TypeError: Cannot read property 'picURL' of undefined.
I've tried a code, which you can see below. It's from "imgRef" and down.
HTML:
<div class="container">
<ul class="posts">
</ul>
</div>
JavaScript:
var postDocRef = db.collection('posts').doc(uid).collection('userPosts')
postDocRef.get().then(snapshot => {
setupPosts(snapshot.docs)
})
const posts = document.querySelector('.posts');
const setupPosts = (data) => {
let html = '';
data.forEach(doc => {
var docRefIDpost = docRef.id
const post = doc.data();
const li = `
<li>
<div class="title">${post.title}</div>
<div class="content">${post.content}</div>
<img class="img">
</li>
`;
var imgRef = db.collection('posts').doc(uid).collection('userPosts').doc(docRefIDpost);
imgRef.get().then(function(snapshot) {
const picURL = snapshot.data().picURL
if (picURL.exists) {
console.log(snapshot.data)
console.log(picURL)
var imgpost = document.querySelector(".img");
imgpost.src = picURL
}
})
html += li
})
posts.innerHTML = html;
}
});
The error is telling you that snapshot.data() returned undefined. As you can see from the API documentation, data() will return undefined when the requested document was not found. It's not clear here why, but your code should check for that first before accessing properties.
imgRef.get().then(function(snapshot) {
const data = snapshot.data()
if (data) {
const picURL = data.picURL
}
else {
// decide what you want to do if the document doesn't exist
}
})

Passing onclick event in template literal

I'm trying to pass url through onclick event, its not working.
there is <body onload="displayBookmarks()"> to initialise displayBookmarks function as soon as the page gets loaded
function deleteBookmark(url){
alert(url);
};
function displayBookmarks(){
bookmarksResults.innerHTML = "";
for (let a in bookmarks){
let name = bookmarks[a].name;
let url = bookmarks[a].url;
bookmarksResults.innerHTML += `<div class="well"> <h3> ${name} <a class="btn btn-default" target="_blank" href=${url} >Visit</a> <a onclick=${deleteBookmark(url)} class="btn btn-danger" >Delete</a></h3></div>`
}
}
The main problem is onclick=${deleteBookmark(url)}
As soon as the page loads it starts displaying the url but I want to to be shown only when delete button is pressed.
I've found that there is another way to do this with encapsulation. I don't know if I would recommend doing it like this at all but since you've asked the question.
const app = document.getElementById("app");
const button = ((app) => {
let _url;
const _log = (data) => {
console.log(data);
}
let _content = `<button onclick="(${_log})('${_url}')">test</button>`;
const _setContent = () => {
_content = `<button onclick="(${_log})('${_url}')">test</button>`;
}
const _setUrl = (url) => {
_url = url;
}
return {
setUrl: (url) => {
_setUrl(url);
_setContent();
},
render: () => {
app.innerHTML = _content;
}
}
})(app)
const url = 'www.something.com';
button.setUrl(url);
button.render();
<section id="app">...</section>
const markUp = `
<button onclick="myFunction()">Click me</button>
`;
document.body.innerHTML = markUp;
window.myFunction = () => {
console.log('Button clicked');
};

Categories

Resources