I'm sure a lot of you have used the TMDb (The Movie Database) api for movies. But I'm having issues with showing the genre names for each movie displayed. I'm trying to replace each number in genre_ids
, from movies api, with their corresponding name
from genres api, as showing numbers to users doesn't say much! But I don't get the desired result. I'm not sure what the correct way is...
Movie adapter
import DS from 'ember-data';
const apiKey = 'SOME_API_KEY_HERE';
export default DS.RESTAdapter.extend({
host: `https://api.themoviedb.org/`,
namespace: '3',
pathForType() {
return `discover/movie?sort_by=popularity.desc&api_key=${apiKey}`;
},
});
Genre adapter
import DS from 'ember-data';
const apiKey = 'SOME_API_KEY_HERE';
export default DS.RESTAdapter.extend({
host: `https://api.themoviedb.org/`,
namespace: '3',
pathForType() {
return `genre/movie/list?api_key=${apiKey}`;
},
});
Movie serializer
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
payload = { movies: payload.results };
return this._super(store, primaryModelClass, payload, id, requestType);
}
});
Genre serializer
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
payload = { genres: payload.genres };
return this._super(...arguments);
}
});
Movie model
import DS from 'ember-data';
const { attr, hasMany } = DS;
export default DS.Model.extend({
vote_count: attr('number'),
video: attr('boolean'),
vote_average: attr('number'),
title: attr('string'),
popularity: attr('number'),
poster_path: attr('string'),
original_language: attr('string'),
original_title: attr('string'),
genre_ids: attr(),
backdrop_path: attr('string'),
adult: attr('boolean'),
overview: attr('string'),
release_date: attr('date'),
});
Genre model
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
});
Route
import Route from '@ember/routing/route';
import RSVP from 'rsvp'
export default Route.extend({
model() {
return RSVP.hash({
movies: this.store.findAll('movie'),
genres: this.store.findAll('genre'),
});
},
});
Movie-listing Component
import Component from '@ember/component';
import { computed } from '@ember/object';
export default Component.extend({
movieGenreIds: computed('[email protected]_ids', function() {
return this.movies.map(movie => movie.genre_ids).reduce((a, b) => [...a, ...b]);
}),
genresNames: computed('movieGenreIds', 'genres', 'movies', function() {
let names = [];
this.genres.map((genre) => {
this.movieGenreIds.forEach(movieGenreId => {
if (parseInt(genre.id) === movieGenreId) {
names.push(genre.name);
}
})
})
return names;
}),
});
Movies API (each movie from the results
array has this structure):
{
"vote_count": 1092,
"id":335983,
"video": false,
"vote_average": 6.7,
"title": "Venom",
"popularity": 505.173,
"poster_path": "/2uNW4WbgBXL25BAbXGLnLqX71Sw.jpg",
"original_language": "en",
"original_title": "Venom",
"genre_ids": [27,878,28,53,35], // <-- I'm interested in this property
"backdrop_path": "/VuukZLgaCrho2Ar8Scl9HtV3yD.jpg",
"adult": false,
"overview": "When Eddie Brock acquires the powers of a symbiote, he will have to release his alter-ego “Venom” to save his life.",
"release_date": "2018-10-03"
}
Genres API
"genres":[
{"id":28,"name":"Action"},
{"id":12,"name":"Adventure"},
{"id":16,"name":"Animation"},
{"id":35,"name":"Comedy"},
...
]
Hbs Template (the expected result)
<ul class="movie">
{{#each movies as |movie|}}
<li>
<h2 class="movie__title">{{movie.title}}</h2>
<p class="movie__genre">
genres:
{{#each genresNames as |genre|}}
{{genre}} <!-- a list of genre names for this particular movie -->
{{/each}}
</p>
<img src="https://image.tmdb.org/t/p/w500/{{movie.poster_path}}" alt="" class="movie__image">
</li>
{{/each}}
See Question&Answers more detail:
os