Home > database >  tt0104779 is not defined at HTMLDivElement.onclick
tt0104779 is not defined at HTMLDivElement.onclick

Time:12-12

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?

  • Related