кінцевий результат
Спочатку отримайте API Token на платформі collect api https://collectapi.com/ та увійдіть за допомогою вашого акаунту Google.
на панелі керування collect api виберіть "Free Plan Available", потім виберіть IMDB API
натисніть кнопку "show", потім перейдіть на вкладку "pricing", виберіть безкоштовний план і підпишіться, збережіть ваш API token, який можна знайти на сторінці профілю, цей API token буде використовуватися для авторизації вашого акаунту.
Встановлення Angular & TailwindCss
Створіть новий проєкт на Angular за допомогою Angular CLI ng new [ім'я проекту]
ng new imdb-clone
зверніть увагу, що у цьому проекті використовується Angular версії 19
Після завершення встановлення, додайте TailwindCss до проєкту, для цього перейдіть у папку проєкту та введіть команду
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
Далі відредагуйте файл tailwind.config.js наступним чином:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
],
theme: {
extend: {},
},
plugins: [],
}
Потім відредагуйте файл ./src/styles.css якщо ви використовуєте CSS
@tailwind base;
@tailwind components;
@tailwind utilities;
або ./src/styles.scss якщо використовуєте SCSS
@import "tailwindcss/base";
@import "tailwindcss/utilities";
@import "tailwindcss/components";
Після цього спробуйте відредагувати файл app.component.html, видаліть весь стандартний код, що додається Angular, та вставте це:
Hello world!
Якщо вигляд відповідає зображенню нижче, то встановлення Tailwind пройшло успішно!
Перехоплювачі (Interceptors)
Оскільки API, який ми використовуємо, вимагає токен авторизації, доцільно застосувати перехоплювачі (interceptors) у Angular.
Що таке перехоплювачі (Interceptors)?
Коротко кажучи, перехоплювачі в Angular — це інструмент для модифікації запитів та відповідей перед їх відправленням або отриманням сервером. Вони використовуються для обробки загальних логік, таких як:
- Додавання headers до кожного запиту.
- Обробка authentication або токенів для оновлення.
- Обробка або модифікація відповіді від сервера.
- Глобальне оброблення помилок (error handling).
Перехоплювачі працюють подібно до "middleware", тобто кожен запит проходить через перехоплювачі перед тим, як потрапити на сервер, а кожна відповідь проходить через перехоплювач перед тим, як потрапити до додатку.
Створення Перехоплювача
Ми можемо створити перехоплювач за допомогою Angular CLI за командою "ng generate interceptor [назваInterceptor]".
Приклад:
ng generate interceptor Authorization
Файл перехоплювача буде створено, і тимчасово структура проєкту виглядатиме так:
Тепер ми інжектуємо файл перехоплювача в додаток. Відкрийте файл src/app/app.config.ts і оновіть код до наступного:
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authorizationInterceptor } from './authorization.interceptor';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient(withInterceptors([authorizationInterceptor]))]
};
що відбувається в коді вище: ми додаємо _provideHttpClient_, який відповідає за надання HTTP клієнта в додаток Angular. Потім всередині нього використовується `withInterceptors` для додавання одного або кількох перехоплювачів (interceptors) до HTTP клієнта. І, нарешті, `authorizationInterceptor` — це перехоплювач (функція або клас), який використовується для модифікації HTTP запитів, що були створені. Пізніше ми додамо заголовок Authorization з токеном, отриманим з Collect API в попередньому кроці.
Модифікуємо файл _authorization.interceptor.ts_
import { HttpInterceptorFn } from '@angular/common/http';
export const authorizationInterceptor: HttpInterceptorFn = (req, next) => {
const authReq = req.clone({
setHeaders: {
Authorization: 'paste api key disini'
}
})
return next(authReq);
};
```
Зверніть увагу: переконайтеся, що ви скопіювали весь API ключ, починаючи з 'apikey xxxxxxx'.
На даному етапі ми успішно отримали API ключ з Collect API, ініціалізували новий проєкт з Angular та Tailwind, і створили перехоплювач (interceptor).
Далі ми створимо сторінку для відображення списку фільмів, деталей фільму та форму для пошуку фільмів, яка буде взаємодіяти з компонентами, формами, сервісами.
Додавання головної сторінки
Тепер створимо просту сторінку як головну сторінку. У цьому підручнику ми не будемо створювати сторінку з дизайном, схожим на сайт IMDb, ви можете налаштувати її на свій розсуд.
Створимо модуль з назвою Home за допомогою Angular CLI
ng g m home
Потім створимо компонент home-index у папці home
ng g c home/home-index --standalone=false
за замовчуванням, коли ви створюєте компонент, який не є standalone, Angular CLI автоматично оновлює файл модуля для декларування компонента, щоб він був розпізнаний
— standalone=false є прапором Angular для того, щоб компонент не був standalone, оскільки в Angular 19 за замовчуванням кожен компонент, який генерується, є standalone, і в цьому підручнику я не хочу використовувати standalone компонент.
Додаємо компонент для деталей фільму
ng g c home/detail-film --standalone=false
Редагуємо файл app_.component.html, щоб він виглядав так
Imdb Lite
Home
import { Component } from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, RouterLink],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'angular-x-collect-api';
}
Редагуємо файл home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HomeIndexComponent } from './home-index/home-index.component';
import { DetailFilmComponent } from './detail-film/detail-film.component';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: ''
},
{
path: '',
component: HomeIndexComponent
},
{
path: 'film/:id',
component: DetailFilmComponent
}
]
@NgModule({
declarations: [
HomeIndexComponent,
DetailFilmComponent
],
imports: [
CommonModule,
RouterModule.forChild(routes)
]
})
export class HomeModule { }
Редагуємо файл app.routes.ts
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
loadChildren: () => import('../app/home/home.module').then(m => m.HomeModule)
}
];
RouterModule, RouterOutlet, RouterLink і loadChildren мають різні функції. Далі ми створимо пояснення про ці функції, чому і коли їх слід використовувати.
Редагуємо файл home-index.component.html
Film 1
Film 2
Film 3
Film 4
Після цього спробуйте запустити додаток Angular. Якщо відображення відповідає зображенню нижче, значить, ми успішно створили просту сторінку.
Далі ми додамо функцію для форми пошуку фільму, щоб дані введені в поле могли бути захоплені і використані як параметри в URL.
Редагуємо файл app.component.ts так:
import { Component } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import {
ActivatedRoute,
Router,
RouterLink,
RouterOutlet,
} from '@angular/router';
import { debounceTime, distinctUntilChanged } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, RouterLink, ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
export class AppComponent {
title = 'angular-x-collect-api';
searchName = new FormControl("marvel");
constructor(private router: Router, private route: ActivatedRoute) {
this.searchName.valueChanges
.pipe(
debounceTime(300) /* Чекаємо 300 мс після того, як користувач перестане друкувати */,
distinctUntilChanged() /* Обробляємо тільки змінені значення */
)
.subscribe((value) => {
this.router.navigate([], {
queryParams: {
query: value
},
queryParamsHandling:
'merge' /* Для збереження інших параметрів запиту */,
});
});
}
deleteFilter() {
this.searchName.reset();
}
}
Редагуємо файл app.component.html
Imdb Lite
Home
@if (searchName.value) { ❌ }
Запустіть додаток, і результат буде таким:
Сервіс
Створимо файл сервісу для отримання даних з API за допомогою Angular CLI
ng generate service home/film
Потім у папці home додаємо ще один файл з назвою imdb.type.ts.
Редагуємо файл imdb.type.ts
export type IMDBRatingType = {
Source: string;
Value: string;
};
export type IMDBListType = {
Title: string;
Year: string;
Poster: string;
Type: string;
imdbID: string;
};
export type IMDBFilmDetailType = {
Title: string;
Year: string;
Rated: string;
Released: string;
Runtime: string;
Genre: string;
Director: string;
Writer: string;
Actors: string;
Plot: string;
Language: string;
Country: string;
Awards: string;
Poster: string;
Ratings: IMDBRatingType[];
Metascore: string;
imdbRating: string;
imdbVotes: string;
imdbID: string;
Type: string;
DVD: string;
BoxOffice: string;
Production: string;
Website: string;
Response: string;
};
Редагуємо файл film.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { IMDBListType } from './imdb.type';
@Injectable({
providedIn: 'root',
})
export class FilmService {
ApiUrl = 'https://api.collectapi.com/imdb/imdbSearchByName';
constructor(private http: HttpClient) {}
getAllFilm(param: Params){
return this.http.get<{ result: IMDBListType[]}>(this.ApiUrl, {
params: param
})
}
}
Ми успішно створили сервіс. Якщо все вірно, можемо продовжити створення головної сторінки.
Якщо ви ще не зрозуміли, що таке сервіс в Angular, ви можете ознайомитись з офіційною документацією Angular або прочитати статтю за наступним посиланням:
Відкрийте файл home-index.component.ts і додайте наступний код:
import { Component } from '@angular/core';
import { IMDBListType } from '../imdb.type';
import { FilmService } from '../film.service';
import { ActivatedRoute, Params } from '@angular/router';
@Component({
selector: 'app-home-index',
templateUrl: './home-index.component.html',
styleUrl: './home-index.component.scss',
})
export class HomeIndexComponent {
filmCollections: IMDBListType[] = [];
params: Params = {}
constructor(
private filmService: FilmService,
private route: ActivatedRoute
){
this.route.parent?.queryParamMap.subscribe((param) => {
if(param.has('query')) {
this.params['query'] = param.get('query')
} else {
this.params['query'] = 'marvel'
}
this.filmService.getAllFilm(this.params).subscribe((res) => {
if(res) this.filmCollections = res.result ?? []
})
})
}
}
Далі редагуємо файл home-index.component.html:
@for (film of filmCollections; track $index) {
{{film.Type}}
{{film.Title}}
{{film.Year}}
}
@empty {
@if (params && !filmCollections.length) {
Немає даних для пошуку {{params['query']}}
} @else {
Фільми не знайдені
}
}
Запустіть додаток і перевірте, чи працює все як має бути. Якщо виникають помилки, перевірте код і переконайтесь, що нічого не пропустили.
Наступним кроком ми перейдемо до створення сторінки для деталей фільму. Раніше ми вже створили основну сторінку для відображення деталей фільму за imdbID. Спробуйте!
Перекладено з: Membuat website mirip IMDB menggunakan Angular, TailwindCss & Imdb collect API #part2