RETRIEVAL AND DISPLAY OF MOVIE LIST FROM API USING A SERVICE

RETRIEVAL AND DISPLAY OF MOVIE LIST FROM API USING A SERVICE

This is the continuation of the post BUILD A MINI NETFLIX APP WITH ANGULAR AND TMDB. the complete code for the app can be found here: github/mini-flix and the deployed version here at netlify mini-flix.netlify .

Let's begin by writing code for the home component of the app we created in the previous post. in order to speed up the process, we will follow this approach: I will write the code first and then explain step by step what it does, you can also clone the complete code from the github repo above and follow along . First, lets open the project root folder and install bootstrap for styling our app.

npm install bootstrap

Next is the implementation of app.component.ts typescript file.

import { Component } from '@angular/core';

Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Movies';


  ngOnInit() {
  };
}

the first line imports the angular core. without this importation then this file will not be recognized as angular code.

The @component decorator identifies the class immediately below it as a component class and specifies its metadata. below are the @component configuration options and their functions.

selector: A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. in this case, the tag name is <app-root>.

templateUrl: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the template property.

styleUrls: Shows the CSS file name which contains styling for the app component.

The AppCompont class which is the class name for this component has a title property with the value Movies and a life cycle hook ngOnInit. life cycle hooks can be used to take action during creation, update and destruction of components as the user moves through the application.

Next, let us create the movie service to start retrieving movies from TMDB API by running the command.

ng generate service movie

if you wish to get an API key of your own or read the TMDB docs, then head over to themoviedb.org. else you can make use of the one provided here.

After the service has been created, we need to import the required modules to be used in creating the functions that will perform operations using the TMDB API endpoint.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';

Let's take a rundown of the imported modules.


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

The HttpClient in @angular/common/http offers a simplified client HTTP API for Angular applications that rests on the XMLHttpRequest interface exposed by browsers. Having imported HttpClientModule, you can inject the HttpClient into an application class as shown in the following.

@Injectable({
  providedIn: 'root'
})

  constructor(private http: HttpClient) { }

Because the service methods returns an Observable of configuration data the calling component can subscribe to, we have to import Observable from rxjs.

import { Observable } from 'rxjs/Observable';

The subscription callback copies the data fields into the component's config object, which is data-bound in the component template for display.

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap

are modules used for customizing search and returned data.

Next, we will set our API key as value to the API_KEY property.

API_KEY = '362f309ced9506f3b5c1f401d7bb73fb';

This API_KEY property will be used as the authentication key when making requests to the TMDB API endpoint. let's go-ahead to define our first method which retrieves a list of current movies from the API endpoint.

getMovies() {
    const api = `https://api.themoviedb.org/3/discover/movie?page=1&include_video=false&include_adult=false&sort_by=popularity.desc&language=en-US&api_key=${this.API_KEY}`;
    return this.http.get(api);
  }

The request is straight forward, the query string contains a request URL with the authentication API key set as value to the api_key attribute.

below is the full source code of the service movies.service.ts with each method name denoting their function.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';

@Injectable({
  providedIn: 'root'
})
export class MovieService {
  API_KEY = '362f309ced9506f3b5c1f401d7bb73fb';


  constructor(private http: HttpClient) { }

  getMovies() {
    const api = `https://api.themoviedb.org/3/discover/movie?page=1&include_video=false&include_adult=false&sort_by=popularity.desc&language=en-US&api_key=${this.API_KEY}`;
    return this.http.get(api);
  }

  getMovie(id: number) {
    console.log(`getMovie ${id} called`)
    const api = `https://api.themoviedb.org/3/movie/${id}?language=en-US&api_key=${this.API_KEY}`;
    return this.http.get(api);
  }
  getMovieList(list_id: number) {
    const api = `https://api.themoviedb.org/3/discover/movie?with_genres=${list_id}&api_key=${this.API_KEY}&language=en-US`;
    return this.http.get(api);
  }

  search(terms: Observable<string>) {
    return terms.debounceTime(400)
      .distinctUntilChanged()
      .switchMap(term => this.searchEntries(term));
  }

  searchEntries(term) {
    const api = `https://api.themoviedb.org/3/search/movie?api_key=${this.API_KEY}&query=${term}`;
    return this.http.get(api);
  }

  getTvShows() {
    const api = `https://api.themoviedb.org/3/tv/popular?api_key=${this.API_KEY}&language=en-US&page=1`;
    return this.http.get(api);
  }
  getPopular() {
    const api = `https://api.themoviedb.org/3/movie/top_rated?api_key=${this.API_KEY}&language=en-US&page=1`;
    return this.http.get(api);
  }


  getUpcoming() {
    const api = `https://api.themoviedb.org/3/movie/upcoming?api_key=${this.API_KEY}&language=en-US&page=1`;
    return this.http.get(api);
  }
}

It's times to make use of these methods to display movies to the user. let's write the code that will perform this function of calling the methods of movie.service.ts in home.component.ts

import { Component, OnInit } from '@angular/core';
import { MovieService } from '../movie.service';


@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
  providers: [MovieService]
})
export class HomeComponent implements OnInit {
  movies;
  constructor( private movieService: MovieService) {  }

  getMovies() {
    this.movieService.getMovies().subscribe(
      data => {
        this.movies = data;
        console.log(data);
      },
      err => console.log(err),
      () => console.log(`success`)
    );

  }

  ngOnInit() {
}
}

In the constructor we defined a property movieService of type MovieService after importing MovieService from movie.service.


import { MovieService } from '../movie.service';
  constructor( private movieService: MovieService) {  }

in getMovies method, we made a call to getMovies of movie.service and subscribed to the returned observable. this returned data is passed to this.movies property of class HomeComponent.

Next , we will see how to display this data to the user. let's begin by writing code for home.component.html .


<div class="container">
    <div *ngIf="movies" class="wrapper" else no_result>

        <div class="row ">

            <div *ngFor="let movie of movies.results | slice:0:11" class="col-sm-3 col-md-3  col-xs-10 col-xs-offset-1 data-div">
                <a routerLink="/detail/{{movie.id}}">
                    <img src="https://image.tmdb.org/t/p/w500/{{movie.poster_path}}" alt="poster" max-width="200px"
                        min-height="150px" class="img img-responsive " />
                    <div class="movie-list-descrip">
                        <span> <span *ngIf="movie.first_air_date">{{movie.first_air_date | date: 'y'}}</span> {{ movie.release_date | date: "y"}} | votes: {{movie.vote_count}}</span>
                    </div>
                </a>
            </div>

        </div>
    </div>
    <ng-template #no_result>No result found</ng-template>
</div>

*ngIf directive checks if movies object is not empty, if it is empty show the no_result template.


    <div *ngIf="movies" class="wrapper" else no_result>

    <ng-template #no_result>No result found</ng-template>

if it contains values, *ngFor is used to iterate through the object and display the required values.

        <div class="row ">

            <div *ngFor="let movie of movies.results | slice:0:11" class="col-sm-3 col-md-3  col-xs-10 col-xs-offset-1 data-div">
                <a routerLink="/detail/{{movie.id}}">
                    <img src="https://image.tmdb.org/t/p/w500/{{movie.poster_path}}" alt="poster" max-width="200px"
                        min-height="150px" class="img img-responsive " />
                    <div class="movie-list-descrip">
                        <span> <span *ngIf="movie.first_air_date">{{movie.first_air_date | date: 'y'}}</span> {{ movie.release_date | date: "y"}} | votes: {{movie.vote_count}}</span>
                    </div>
                </a>
            </div>

        </div>
    </div>

below is the css styles of home.component.css

body {
    background:rgb(22, 3, 3);
}
.wrapper{
    padding-top:40px;
    padding-bottom:30px;
}
a:hover{
    text-decoration:none;
}
.movie-list-descrip{
  background:navajowhite;
 width: 100%;
  color:rgb(22, 3, 3);
    text-align:center;
}

before we run our app we have to add home.component to app.component.html using it's selector like this:

app.component.html

<div>{{title}}</div>
<app-home></app-home>

run the following command to start our app and see our progress so far.

ng serve

when compiled successfully as shown in the terminal, navigate to localhost:4200 in your browser. you should see this:

see_this.PNG

In the next post, we will implement the movie-details component to show details of each movie when clicked. and the navigation component for routing. enjoy your new app!