Skip to content

imdb api.com: HTTP GET implementation

Michael Gilson edited this page Jul 11, 2021 · 2 revisions

IMDB-API.COM: HTTP GET IMPLEMENTATION


Setup

  • in the app.module.ts:
    • import { HttpClientModule } from '@angular/common/http';
    • add HttpClientModule to "imports"
  • create an api service from command line: ng generate service [filename] (ours uses "apicall")
    • this generates apicall.service.ts file
  • in the apicall.service.ts:
    • add the following imports:
      • import { HttpClient } from '@angular/common/http';
      • import { from, Observable, throwError } from 'rxjs';
      • import { map, catchError } from 'rxjs/operators';
    • update the constructor:
      • constructor(private http: HttpClient) {}

Generate API Key with imdb-api-com / get JSON results

  • Create account - this account allows for 100 api calls/day.
  • go to Profile page to see your API Key.
  • once signed in, you can go to the API Tester page to try out various api calls using your API key.
    • NOTE: These test calls will count toward your 100/day limit.
    • a new tab will open showing the returned data in JSON format.
    • To search for matches to a move title: https://imdb-api.com/en/API/SearchMovie/[apikey]/[moviename]

Create Interface file for data return type

  • create interface for your desired data return type from command line: ng generate interface [name] (I used "movies")
    • this generates a file: `movies.ts' (which will be blank). For each data set you want to have returned, you will want to create an interface to define the returned data. There is a handy tool that will take a sample of returned json and translate that to the interface attributes.
  • MakeTypes
    • Copy/paste your returned json information into the input field, give it a title, and hit the Generate button.
    • resulting Interface code will be generated in the upper Output field. This can then be copy/pasted into the Interface file.
    • From the movies.ts interface:
    export interface Movies {
        searchType: string;
        expression: string;
        results?: (MovieItem)[] | null;
        errorMessage: string;
    }
    
    export interface MovieItem {
        id: string;
        resultType: string;
        image: string;
        title: string;
        description: string;
    }
    

Create API GET method

  • in apicall.service.ts:
    • add import to top of file: import { Movies, MovieItem } from './movies';
    • create Get Method within the ApicallService class.
      • include paramaters after method name, and the type of Observable object to be returned.
      • in the return statement, call http.get, the type to be referenced, and the API string.
        • in the code example, the API key has been replaced with an environment variable for security, and the movieName is from the provided parameter, with encodeURIComponent to replace spaces with %20. -Angular uses a pipe() call with a map function. For each data returned, it will return the results from the return Object (Movies.results from our interface) or will return an empty array.
      • the console.log(data) line is for verifying the get call works.
    getMovies(movieName: string): Observable<MovieItem[]> {
        return this.http.get<Movies>(`https://imdb-api.com/en/API/SearchMovie/${environment.imdbApiKey}/${encodeURIComponent(movieName)}`).
            pipe(
              map((data) => {
                console.log(data);
                return data.results ?? [];
              })
            )
    }
    

Component retrieval

Whichever component will be displaying the info will need the following additions (I used the app.component.ts for proof of concept:

  • import { ApicallService } from './apicall.service'; to reference the apicall.service.ts file

  • import type { MovieItem } from "./movies"; to reference the MovieItems in the movies.ts file

  • class variable to define the data: `Movie: MovieItem[] = [];' --> "Movie" will be an empty array of "MovieItem[]"s.

  • loadMovies() method to "subscribe" to the GET API call. For our getMovies method, I added a loadMovies() method to the app.component.ts:

    loadMovies() {
       return this.apicall.getMovies("Star Wars").subscribe((data) => {
            this.Movie = data;
       })
    }
    
    • here, the return references the apicall.service.ts's getMovies method, with a movie name as a parameter. It "subscribes" to this method, where the "data" being returned is stored to our previously declared Movie variable.
  • NOTE: My code has the loadMovies() method being called on page load (via the ngOnInit() method). We would eventually want to change this to a "onClick" when a user hits "search" after typing in their desired movie title.

Displaying information on the page

To have the Component display the information it has retrieved, we will need to add code to the component's html file. In the above example, the compnent has stored the information in a Movie variable. this will be referred to in the Angular code in the html file.

Displaying a particular attribute on the page:

  • As a test, I added a div with an h3 to display an imdb id of one of the returned movies. I use {{ }} to encapsulate Angular code that setup an "if" statement and conditions, since these were being referenced on page load.
    • If the Movie variable was undefined, it would display a "Loading..." message.
    • Otherwise, if the Movie array length was 0, it would display a "No results" message.
    • Otherwise, it would display the imdb id of the requested movie name.
    <div>
      <h3>
        {{
          Movie === undefined
            ? "Loading..."
            : Movie.length === 0
            ? "No results"
            : Movie[0].id
        }}
      </h3>
    </div>
    

Displaying a table of all Movie items returned:

  • I included a div with a table that would display all attributes of the returned array of MovieItems.
  • I used TypeScript's *ngFor to create html for each item in the Movie array, referencing each of the Interface elements using {{ }}:
    <div class="col-md-12">
      <table class="table table-bordered">
        <thead>
          <tr>
            <th scope="col">Id</th>
            <th scope="col">Type</th>
            <th scope="col">image</th>
            <th scope="col">title</th>
            <th scope="col">desc</th>
          </tr>
        </thead>
        <tbody>
          **<tr *ngFor="let movie of Movie">**
            <td>{{ movie.id }}</td>
            <td>{{ movie.resultType }}</td>
            <td><img src="{{ movie.image }}" style="height: 100px" /></td>
            <td>{{ movie.title }}</td>
            <td>{{ movie.description }}</td>
          </tr>
        </tbody>
      </table>
    </div>
    

Updating environments variable with API key and adding to .gitignore

  • In src/environments/environment.ts, update the code with the following:
    export const environment = {
      production: false,
      **imdbApiKey: "[your API key]"**
    };
    
  • add src/environments/* to the .gitignore file, to ensure your api key isn't uploaded to github.