In this tutorial, we’ll learn how to integrate a YouTube API in Angular.
The YouTube Data API lets you incorporate functions normally executed on the YouTube website into your own website or application. We can retrieve a list of different types of resources from the API. A resource represents a type of item that comprises part of the YouTube experience, such as a video, a playlist, or a subscription.
First you need to set YouTube API key to integrate it in the project.
To get API key follow the below steps:
+ CREATE CREDENTIALS
button located at the top of the page and select API key.
A new API key should be created.Create a new project from terminal in VS code by using following command.
ng new YouTubeAPI
here we need to create component for search box and container.
Create a new module called shared by running the following command in the terminal.
ng g module shared
now let’s create a service in this module by using following command in terminal.
ng g service shared/services/search
write the code in search.service.ts file as below:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SearchService { private API_URL = 'https://www.googleapis.com/youtube/v3/search'; private API_KEY = 'YOUR API KEY'; constructor(private http: HttpClient) {} getVideos(query: string): Observable <any> { const url = `${this.API_URL}?q=${query}&key=${this.API_KEY}&part=snippet&type=video&maxResults=10`; return this.http.get(url) .pipe( map((response: any) => response.items) ); } }
The getVideos method receives a search query string passed in from the input component, which we have to create. It then uses the http
get method to send off a request to the URL constructed. It returns a response that we handle with the map operator. The list of YouTube video details is stored in the response.item object.
Now create interface. Run following command
ng g interface video
Add the following code in interface
export interface Video { videoId: string; videoUrl: string; channelId: string; channelUrl: string; channelTitle: string; title: string; publishedAt: Date; description: string; thumbnail: string; }
We will be using Semantic-UI to provide styling to our application.
Add the following line in index.html file
<div class="ui four column grid"> <div class="ten wide column centered"> <div class="ui fluid action input"> <input #input type="text" placeholder="Search for a video..."> </div> </div> </div>
Next, add following code in search-input.component.ts file.
import { Component, ElementRef, EventEmitter, Output, ViewChild, AfterViewInit } from '@angular/core'; import { fromEvent,distinctUntilChanged } from 'rxjs'; import { debounceTime, pluck } from 'rxjs/operators'; @Component({ selector: 'app-search-input', templateUrl: './search-input.component.html', styleUrls: ['./search-input.component.css'] }) export class SearchInputComponent implements AfterViewInit { @ViewChild('input') inputElement!: ElementRef; @Output() search: EventEmitter<string> = new EventEmitter<string>(); constructor() { } ngAfterViewInit() { if (this.inputElement) { fromEvent(this.inputElement.nativeElement, 'keyup') .pipe( debounceTime(500), pluck('target', 'value'), distinctUntilChanged(), ) .subscribe( value => { this.search.emit(this.inputElement.nativeElement.value)} ) } } }
ViewChild (‘input’) gives us access to the input element defined in the HTML file. ‘input’ is a selector that refers to the #input template reference variable we previously added to the input element in the HTML file.
formEvent is used to set up event listeners on a specific element.
debounceTime used to control the rate of user input.
import { Component, Input, OnInit } from '@angular/core'; import { Video } from '../../../shared/models/search.interface'; @Component({ selector: 'app-search-list', templateUrl: './search-list.component.html', styleUrls: ['./search-list.component.css'] }) export class SearchListComponent implements OnInit { @Input() videos: Video[] | undefined; constructor() { } ngOnInit(): void { } }
Here, Input decorator is used to get vidoes list from the parent component.
<div class="ui four column grid"> <div class="column" *ngFor="let video of videos"> <div class="ui card"> <div class="image"> <img [src]="video.thumbnail"> </div> <div class="content"> <a class="header" style="margin: 1em 0 1em 0;">{{ video.title }}</a> <div class="meta"> <span class="date" style="font-weight: bolder;"> <a [href]="video.channelUrl" target="_blank">{{ video.channelTitle }}</a> </span> <span class="ui right floated date" style="font-weight: bolder;">{{ video.publishedAt | date:'mediumDate' }}</span> </div> <div class="description"> {{ video.description?.slice(0,50) }}... </div> </div> <a [href]="video.videoUrl" target="_blank" class="extra content"> <button class="ui right floated tiny red right labeled icon button"> <i class="external alternate icon"></i> Watch </button> </a> </div> </div> </div>
let’s create parent component for search-list component.
ng g c search/search-container
This component should be able to get user inputs from the search-component component. It should pass this over to the search service, which does the operations and returns the expected result. The result should be send to the search-list component, where it will be rendered.
import { Component, OnInit } from '@angular/core'; import { Video } from 'src/app/shared/models/search.interface'; import { SearchService } from 'src/app/shared/services/search.service'; @Component({ selector: 'app-search-container', templateUrl: './search-container.component.html', styleUrls: ['./search-container.component.css'] }) export class SearchContainerComponent { inputTouched = false; loading = false; videos: Video[] = []; constructor(private searchService: SearchService) { } handleSearch(inputValue: string) { this.loading = true; this.searchService.getVideos(inputValue) .subscribe((items : any) => { this.videos = items.map((item => { return { title: item.snippet.title, videoId: item.id.videoId, videoUrl: `https://www.youtube.com/watch?v=${item.id.videoId}`, channelId: item.snippet.channelId, channelUrl: `https://www.youtube.com/channel/${item.snippet.channelId}`, channelTitle: item.snippet.channelTitle, description: item.snippet.description, publishedAt: new Date(item.snippet.publishedAt), thumbnail: item.snippet.thumbnails.high.url }; }); this.inputTouched = true; this.loading = false; }); } }
serch-container.component.html
<div> <app-search-input (search)="handleSearch($event)"></app-search-input> <div *ngIf="inputTouched && !videos.length" class="ui four wide column centered grid" style="margin: 3rem;"> <div class="ui raised aligned segment red warning message"> <i class="warning icon"></i> <span class="ui centered" style="margin: 0 auto;">No Video Found</span> </div> </div> <div *ngIf="loading" style="margin: 3rem;"> <div class="ui active centered inline loader"></div> </div> <app-search-list *ngIf="!loading" [videos]="videos"></app-search-list> </div>
Here, serach servise use the HttpClient, so we have to import HttpClientModule in app.module.ts file.
Paste the following code in app.module.ts file.
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import {HttpClientModule} from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { SearchInputComponent } from './search/components/search-input/search-input.component'; import { SearchListComponent } from './search/components/search-list/search-list.component'; import { SearchContainerComponent } from './search/container/search-container/search-container.component'; @NgModule({ declarations: [ AppComponent, SearchInputComponent, SearchListComponent, SearchContainerComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
app.component.html
<div class="ui centered grid" style="margin-top: 3rem;"> <div class="fourteen wide column"> <h1 class="ui centered aligned header"> <span style="vertical-align: middle;">Youtube Search </span> <img src="/assets/youtube-icon.png" alt=""> </h1> <app-search-container></app-search-container> </div> </div>
OUTPUT:
In this article, we have to show Create and Used PIPE in angular
In this article, we have to show Create and Used PIPE in angular
In this article, we have to show Create and Used PIPE in angular