Im facing a problem trying to understand why whenever i clicked a movie that im fetching from the omdb api in order to get a new page that has more details of the movie itself it throws this error: this is the error im facing
this is the code: the error comes whenever i try to call the showmoviePost function
const moviesList = document.querySelector(".books")
let contrastToggle = false;
let imdbID = ""
async function main() {
const movies = await fetch ("https://www.omdbapi.com/?apikey=97f5b4c9&s=spider");
const moviesData = await movies.json();
moviesList.innerHTML = moviesData.Search.map((movie) => moviesHTML(movie)).join("");
}
main()
function moviesHTML(movie) {
return `<div onclick="showMoviePost(${movie.imdbID})">
<figure >
<img src=${movie.Poster} alt="">
</figure>
<div >
${movie.Title} - ${movie.Year}
</div>
<div >
${movie.Type}
</div>
</div>`
}
function toggleContrast() {
contrastToggle = !contrastToggle;
if (contrastToggle) {
document.body.classList = " dark-theme"
} else {
document.body.classList.remove("dark-theme")
}
}
//`http://127.0.0.1:5500/user-posts-starter/user.html`
//${window.location.imdbID}
function showMoviePost(imdbID) {
localStorage.setItem("imdbID", imdbID);
window.location.href = `http://127.0.0.1:5501/movie.html`
}
I have 2 days trying to look for the error through out the internet but i havent found a solution yet
CodePudding user response:
Presumably the movie.imdbID
property is a string and not just a number. You would need to quote the parameter to use it as you are but a better option would be to use data attributes and read them from the element in the event handler.
return `<div data-imdb-id="${movie.imdbID}">...`;
You can add a delegated event handler on moviesList
and check for clicks on your .book
elements...
moviesList.addEventListener("click", (e) => {
const book = e.closest(".book[data-imdb-id]");
if (book) {
showMoviePost(book.dataset.imdbId);
}
});
Creating HTML strings is fraught with issues around quoting and encoding. I would highly recommend using DOM methods to create elements
const createElement = (type, attributes, ...children) => {
const elt = document.createElement(type);
Object.entries(attributes).forEach(([attr, val]) => {
elt.setAttribute(attr, val);
});
elt.append(...children);
return elt;
};
const createBook = (movie) =>
createElement(
"div",
{ class: "book", "data-imdb-id": movie.imdbID },
createElement(
"figure",
{ class: "book__img_wrapper" },
createElement("img", { class: "book_img", src: movie.Poster })
),
createElement(
"div",
{ class: "book__title" },
`${movie.Title} - ${movie.Year}`
),
createElement("div", { class: "book__ratings" }, movie.Type)
);
CodePudding user response:
You are using template literal to generate HTML. In a template literal. ${x}
is replaced by the result of evaluation of the expression x
. Thus,
return `<div onclick="showMoviePost(${movie.imdbID})">...`
results in the string
"return `<div onclick="showMoviePost(tt0104779)">..."
When you then use this as HTML and click on the resultant element, JavaScript tries to execute showMoviePost(tt0104779)
, but to do that it has to know the value of the variable tt0104779
, which obviously is not defined.
Instead, make sure you have the string in your code, rather than a bare identifier:
return `<div onclick="showMoviePost(${JSON.stringify(movie.imdbID}">...`
You could also think you could just put quotes in there:
return `<div onclick="showMoviePost('${movie.imdbID}')">...`
... but that is not as safe — what if movie.imdbID
has a quote character?