0

I'm currently getting data from themoviedb.com API. but I discovered the request doesn't include the specific genres for each movie. I created a separate json file that contains all the genres I need. Is there a way I can map data in my genres.json files to the remote API request?

{
  "genres": [
    {
      "id": 28,
      "name": "Action"
    },
    {
      "id": 12,
      "name": "Adventure"
    },
    {
      "id": 16,
      "name": "Animation"
    },
    {
      "id": 35,
      "name": "Comedy"
    },
    {
      "id": 80,
      "name": "Crime"
    },
    {
      "id": 99,
      "name": "Documentary"
    },
    {
      "id": 18,
      "name": "Drama"
    },
    {
      "id": 10751,
      "name": "Family"
    },
    {
      "id": 14,
      "name": "Fantasy"
    },
    {
      "id": 36,
      "name": "History"
    },
    {
      "id": 27,
      "name": "Horror"
    },
    {
      "id": 10402,
      "name": "Music"
    },
    {
      "id": 9648,
      "name": "Mystery"
    }
  ]
}
2
  • What does the request response look like? Commented Feb 21, 2018 at 14:38
  • It looks like this I only get the genres_id from the API. i want to map the data above to the genres_id here api.themoviedb.org/3/movie/… Commented Feb 21, 2018 at 14:45

2 Answers 2

1

This is how you might do that.

Basically with Vue, you want to create a computed value that maps over the response from the movie API and adds the genre information to the response.

console.clear()
const genres = [
    {
      "id": 28,
      "name": "Action"
    },
    {
      "id": 12,
      "name": "Adventure"
    },
    {
      "id": 16,
      "name": "Animation"
    },
    {
      "id": 35,
      "name": "Comedy"
    },
    {
      "id": 80,
      "name": "Crime"
    },
    {
      "id": 99,
      "name": "Documentary"
    },
    {
      "id": 18,
      "name": "Drama"
    },
    {
      "id": 10751,
      "name": "Family"
    },
    {
      "id": 14,
      "name": "Fantasy"
    },
    {
      "id": 36,
      "name": "History"
    },
    {
      "id": 27,
      "name": "Horror"
    },
    {
      "id": 10402,
      "name": "Music"
    },
    {
      "id": 9648,
      "name": "Mystery"
    }
  ]

new Vue({
  el: "#app",
  data:{
    genres,
    movies: null
  },
  computed:{
    moviesWithGenre(){
      // if the movies haven't been populated from the AJAX response yet
      // return an empty array
      if (!this.movies) return []
      
      return this.movies.map(movie => {
        return {
          // add all the existing movie properties
          ...movie,
          // add the genres
          genres: movie.genre_ids
                    // remove the genres we don't know
                    .filter(id => this.genres.map(g => g.id).includes(id))
                    // get the name
                    .map(id => this.genres.find(g => g.id === id).name)
        }
      })
    }
  },
  created(){
    var url = "https://api.themoviedb.org/3/movie/popular?api_key=8e3003c0c81633dc53b9d15ffa3399e1&language=en-US&page=1"
    axios.get(url)
      .then(response => this.movies = response.data.results)
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<div id="app">
  <ul>
    <li v-for="movie in moviesWithGenre">
      {{movie.original_title}}
      <ul>
        <li v-for="g in movie.genres">{{g}}</li>
      </ul>
    </li>
  </ul>
</div>

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for this solution. I tried this not working for me. First of all, I'm calling the movie.genre_ids in child component. Secondly, do you think it's better calling the genres fro the API like so developers.themoviedb.org/3/genres/get-movie-list instead of having it in a file?
@LauraNdidi What do you mean you are calling the genre_ids in a child? They are included in the response. As far as getting the genre list from the API, I would imagine it depends on how often the list changes. If it's relatively static, you could save yourself time not having to continually call it, but if you wanted to always be as up to date as possible, you could make the call. If you did make the call, you would handle the possibility of getting data at different times (not that hard in Vue).
Alright. I mean I have a parent component right and a child component a modal where I want to display the genres. So I'm not directly calling it inside the same component. if this makes sense
@LauraNdidi Well, let's assume you get the data in a parent and pass the single movie to the child. You can either add the genres in the parent and pass the movie with the genres to the child, or you can make a computed that adds the genres to the passed movie in the child. In either case, the approach is pretty much the same; make a computed value that adds the genres to your movie/s.
0

I do not understand how any of this is related to vue.js as it looks like a pure javascript logic problem. Here are some advices that could help you :

Rather than keeping an hardcoded list of Categories which is susceptible to get outdated and to break your application, i would recommend you to get them from the api itself : https://developers.themoviedb.org/3/genres/get-movie-list

When having the result of both your genres and find request you could add the genre names to the object you are getting like so :

// Here the result of the 'genres' call
var genres = [...]

function getGenreName(genreId) {
  var genre = genres.find(function(element) {
    return element.id === genreId
  })
  if (!genre) return 'unknownGenre'
  return genre.name
}

movieResults.map(function(movieResult) {
  movieResult['genreNames'] = movieResult.genre_ids.map(function(genreId) {
    return getGenreName(genreId)
  })
  return movieResult
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.