U ovom ću blog postu pokazati kako koristiti Marvel API unutar Angular projekta. Fokus će biti na pravilnoj konfiguraciji API-ja nakon koje je moguće, prema dokumentaciji, koristeći različite parametre dobiti konkretne rezultate.
O Marvel API-ju
Marvel API je RESTful alat koji pomaže developerima stvoriti web stranice i aplikacije pomoću podataka iz 70 godišnje povijesti Marvela. Trenutno je dostupno šest vrsta resursa kao što su individualni stripovi (Comics), grupe ili serije stripova (Comic series), dijelovi pojedinih stripova (Comic stories), veliki događaji iz pojedinih stripova (Comic events and crossovers), žene, muškarci i organizacije koji su kreatori stripova (Creators) i likovi iz stripova (Characters).
Originalna putanja za pristup resursima nalazi se na http(s)://gateway.marvel.com/ i trenutno je moguće koristiti samo GET metodu.
Svaki zahtjev koji se uputi na gore navedeni URL mora u sebi sadržavati nekoliko parametara koji se dobiju nakon registracije.
API koji ću koristiti u nastavku ima sljedeći oblik
http://gateway.marvel.com/v1/public/comics?ts=1&apikey=1234&hash=ffd275c5130566a2916217b101f26150
iz čega je vidljivo da se sastoji od tri glavna parametra
- apikey = PublicKey
- ts – timestamp (or other long string which can change on a request-by-request basis)
- hash – md5 ključ ts parametra (npr. md5(ts+privateKey+publicKey))
Postavljanje Angular projekta
Koristeći Angular CLI kreiram novi projekt naredbom
1 2 3 |
$ ng new AngularMarvelAPI $ cd AngularMarvelAPI $ ng serve |
Odmah ću kreirati i servis za API koristeći naredbu
1 |
$ ng g service api |
Kao što se može vidjeti na slici iznad API servis trenutno ne zadovoljava potrebne preduvjete za uspješno korištenje. S obzirom da će taj servis primarno biti korišten za pozivanje HTTP(S) protokola moram dodati @angular/http. Također, koristiti ću i map operator koji će dobivenu vrijednost transformirati u JSON. Na kraju, prema ranije spomenutoj Marevl API dokumentaciji, moram koristiti MD5 hash, u tome će mi pomoći ts-md5 NPM paket koji instaliram naredbom $ npm i ts-md5 --save.
API servis na kraju izgleda ovako
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add/operator/map'; import { Md5 } from 'ts-md5/dist/md5'; var PrivateKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; var PublicKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; var TimeStamp = new Date().getTime(); var hash = Md5.hashStr(TimeStamp + PrivateKey + PublicKey).toString(); @Injectable() export class ApiService { constructor(private _http: Http) { } allHeroes(){ return this._http.get('http://gateway.marvel.com/v1/public/characters?ts=' + TimeStamp + '&apikey=' + PublicKey + '&hash=' + hash + '&limit=100') .map(res => res.json()); } } |
Sada taj servis mogu koristiti u bilo kojem dijelu Angular aplikacije. Za potrebu ovog primjera zadržat ću se na app.component.ts.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ApiService] }) export class AppComponent implements OnInit { heroes = []; constructor(public _apiService: ApiService) { } ngOnInit() { this.getAllHeroes(); } getAllHeroes(){ this._apiService.allHeroes().subscribe( res => { console.log(res); for (let i = 0; i < res.data.results.length; i++) { if(res.data.results[i].description.length > 1){ this.heroes.push({ id: res.data.results[i].id, name: res.data.results[i].name, description: res.data.results[i].description, modified: res.data.results[i].modified, image: res.data.results[i].thumbnail.path + '.' + res.data.results[i].thumbnail.extension, details_url: res.data.results[i].urls[0].url }) } } console.log(this.heroes); }); } } |
Otvaranjem http://localhost:4200/ adrese odmah se dohvaćaju Marvel likovi sa ranije kreiranog API-ja.
Na kraju to može izgledati i ovako
Na slici iznad se može primijetiti da je prikaz vremena lijepo formatiran i da tako nije izgledao ranije u animaciji. Za to je zaslužan MomentJS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; import * as moment from 'moment'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ApiService] }) export class AppComponent implements OnInit { heroes = []; constructor(public _apiService: ApiService) { } ngOnInit() { this.getAllHeroes(); } getAllHeroes(){ this._apiService.allHeroes().subscribe( res => { console.log(res); for (let i = 0; i < res.data.results.length; i++) { if(res.data.results[i].description.length > 1){ this.heroes.push({ id: res.data.results[i].id, name: res.data.results[i].name, description: res.data.results[i].description, modified: moment(res.data.results[i].modified).format('LL'), image: res.data.results[i].thumbnail.path + '.' + res.data.results[i].thumbnail.extension, details_url: res.data.results[i].urls[0].url }) } } console.log(this.heroes); }); } } |
Zaključak
Iz cijelog ovog blog posta najvažniji dio je API servis koji sadržava sve potrebno za uspješan dohvat podataka sa Marvel API-ja. Prikaz podataka radi se ovisno o potrebama od slučaja do slučaja. Konkretno u ovom blog postu fokus je bio na uspješnom dohvatu podataka.
Struktura projekta prema package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
{ "name": "angular-marvel-api", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build --prod", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^5.2.0", "@angular/common": "^5.2.0", "@angular/compiler": "^5.2.0", "@angular/core": "^5.2.0", "@angular/forms": "^5.2.0", "@angular/http": "^5.2.0", "@angular/platform-browser": "^5.2.0", "@angular/platform-browser-dynamic": "^5.2.0", "@angular/router": "^5.2.0", "core-js": "^2.4.1", "moment": "^2.22.1", "rxjs": "^5.5.6", "ts-md5": "^1.2.4", "zone.js": "^0.8.19" }, "devDependencies": { "@angular/cli": "~1.7.4", "@angular/compiler-cli": "^5.2.0", "@angular/language-service": "^5.2.0", "@types/jasmine": "~2.8.3", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", "codelyzer": "^4.0.1", "jasmine-core": "~2.8.0", "jasmine-spec-reporter": "~4.2.1", "karma": "~2.0.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~4.1.0", "tslint": "~5.9.1", "typescript": "~2.5.3" } } |