1

I'm trying to add an autocomplete to a simple form input (movie title) based on the API "the movie DB" (https://developers.themoviedb.org/3/search/search-movies).

const findMovies = (wordToMatch) => {
        const url = `https://api.themoviedb.org/3/search/movie?api_key=263e31d1ad0c4defa8822787e614e716&language=en-US&query=${wordToMatch}&page=1&include_adult=false`
        const movies = [];
        fetch(url)
          .then(blob => blob.json())
          .then(data => data.results.forEach(result => movies.push(result.original_title)));
        return movies;
    }

    function displayMovies() {
      const moviesArray = findMovies(this.value);
      const html = moviesArray.map(movie => {
        return `
          <li>
            <span class="movie">${movieName}</span>
          </li>
        `;
      });
      suggestions.innerHTML = html;
    }

    const titleInput = document.querySelector("#memory_cultural_good_attributes_title");
    const suggestions = document.querySelector('.suggestions');

    if (titleInput) {
        titleInput.addEventListener("keyup", displayMovies);
    }
<%= movie_form.input :title %>
   <ul class="suggestions">
   </ul>

The findMovies function works well and returns an array of the movies according to the input of the user. The problems seems to be when I iterate over this array (moviesArray) in the displayMovies function it is not giving the expected results.

Indeed, when I log the result of html in my console, it's empty. It seems that the map didn't work on the moviesArray. I was wondering if maybe moviesArray would not be an array, but if I print the array in console like this console.log(Array.isArray(moviesArray)) then, I get "true" as a response.

Hope my question is clear (this is my first one here), don't hesitate to ask me for additional details.

Many thanks !

Soumen Mukherjee
  • 2,953
  • 3
  • 22
  • 34
  • If I were you, I think I would move most of that code back onto the server. – jvillian Sep 16 '19 at 14:55
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – 3limin4t0r Sep 16 '19 at 14:58

1 Answers1

2

you can't return movies in this way, because the http call is asynchronous, you have to wait the result and use a callback function or use a promise to wait the result and then you can populate movies.

You do it already when you write .then and do some things inside. So you can use fondMovies as the first function to call, and instead of the foreach you can call displayMovies and run foreach inside the displaymovies function.

like this:

const findMovies = (wordToMatch) => {
    const url = `https://api.themoviedb.org/3/search/movie?api_key=263e31d1ad0c4defa8822787e614e716&language=en-US&query=${this.value}&page=1&include_adult=false`
    const movies = [];
    fetch(url)
      .then(blob => blob.json())
      .then(data => displayMovies(data));
}

function displayMovies(data) {
  const moviesArray = []
data.results.forEach(result => movies.push(result.original_title))
  const html = moviesArray.map(movie => {
    return `
      <li>
        <span class="movie">${movieName}</span>
      </li>
    `;
  });
  suggestions.innerHTML = html;
}

const titleInput = document.querySelector("#memory_cultural_good_attributes_title");
const suggestions = document.querySelector('.suggestions');

if (titleInput) {
    titleInput.addEventListener("keyup", findMovies);
}
Pasquale De Lucia
  • 190
  • 1
  • 1
  • 12
  • 2
    Thank you very much Pasquale, that works like that. I've suggested some small changes to your code that I had to make so it works. Again, thanks a lot ! – Mavrick Munoz Sep 17 '19 at 08:24