-
Notifications
You must be signed in to change notification settings - Fork 1
imdb api.com: HTTP GET implementation
- 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
- this generates
- 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) {}
- add the following imports:
- 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 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; }
- 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 apipe()
call with amap
function. For eachdata
returned, it will return theresults
from the return Object (Movies.results
from our interface) or will return an empty array.
- 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
- the
console.log(data)
line is for verifying the get call works.
- include paramaters after method name, and the type of
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 ?? []; }) ) }
- add import to top of file:
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 theapicall.service.ts
file -
import type { MovieItem } from "./movies";
to reference theMovieItems
in themovies.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 ourgetMovies
method, I added aloadMovies()
method to theapp.component.ts
:loadMovies() { return this.apicall.getMovies("Star Wars").subscribe((data) => { this.Movie = data; }) }
- here, the return references the
apicall.service.ts
'sgetMovies
method, with a movie name as a parameter. It "subscribes" to this method, where the "data" being returned is stored to our previously declaredMovie
variable.
- here, the return references the
-
NOTE: My code has the
loadMovies()
method being called on page load (via thengOnInit()
method). We would eventually want to change this to a "onClick" when a user hits "search" after typing in their desired movie title.
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 theMovie
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>
- 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.