Build an application movies with Spring boot and Angular part 2

Getting Started | Building an Application with Angular




Angular 10 Front-end

In this tutorial We are going build an application Movies to display the movies we will use the query find by title, find by year, find by director and find by actor. we use mongodb database to develope this project. Front-end side is made with Angular 10, HTTPClient & Router.


Angular CLI version (10.1.1)

ng new

The Angular CLI makes it easy to create an application that already works, right out of the box. It already follows our best practices!


ng generate

Generate components, routes, services and pipes with a simple command. The CLI will also create simple test shells for all of these.


ng serve

Easily test your app locally while developing.



$  npm install -g @angular/cli
$ ng new movies
$ cd movies
$ ng serve

Technology

Angular 10

Angular HTTPClient

Angular Router


Project Structure


Install Bootstrap CSS framework

Bootstrap a framework to encourage consistency across internal tools. Before Bootstrap, various libraries were used for interface development, which led to inconsistencies and a high maintenance burden. According to Twitter developer Mark Otto:

Use the following command to install bootstrap in the project.


$  npm install bootstrap --save

Install Pagination

The ngx-pagination offers the simplest yet powerful solution for making pagination in Angular. All hail to its flexibility and responsiveness, customization is pretty handy with ngx-pagination, and yes its is loaded with some beautiful themes too.

Use the following command to install bootstrap in the project.


$  npm install ngx-pagination --save

src/style.css

First of all, we need to create the various entry point CSS files of course. You can just create further scss files at the level where the styles.scss is in your project.


src/style.css


@import '~bootstrap/dist/css/bootstrap.min.css'; table { font-family: "Lato", "sans-serif"; width: 100%; } table.one{ margin-bottom: 3em; border-collapse: collapse; } td { text-align: center; width: 10em; padding: 1em; } th { text-align: center; padding: 1em; background-color: #e8503a; color: white; } tr { height: 1em; } table tr:nth-child(even) { background-color: #eee; } table tr:nth-child(odd) { background-color: #fff; } h2 { color: #8e9195; font-family: initial; } .lds-hourglass { display: inline-block; position: relative; width: 80px; height: 80px; } .lds-hourglass:after { content: " "; display: block; border-radius: 50%; width: 0; height: 0; margin: 8px; box-sizing: border-box; border: 32px solid #fff; } .loader { border: 16px solid #f3f3f3; border-radius: 50%; border-top: 16px solid #007bff !important; width: 100px; height: 100px; -webkit-animation: spin 2s linear infinite; animation: spin 2s linear infinite; margin-left: 100px; } @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); } } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

Introduction to components and templates

A component controls a patch of screen called a view. For example, individual components define and control each of the following views from the Tour of application tutorial:


You define a component's application logic—what it does to support the view—inside a class. The class interacts with the view through an API of properties and methods.


src/app/app-component.html


<ul class="nav nav-tabs" style="background: #e8503a; color: white;"> <li class="nav-item"> <a class="nav-link" [routerLink]="['/findAllArtistes']">Artistes</a> </li> <li class="nav-item"> <a class="nav-link" [routerLink]="['/findAllMovies']">Movies</a> </li> <li class="nav-item"> <a class="nav-link" [routerLink]="['/query-movies']">Queries movies</a> </li> </ul> <div style="padding-bottom: 20px;"> <router-outlet></router-outlet> </div>

Model

Let's create classes by using the following command


$  ng g class ClassName

The purpose of this class is to map the specified fields with the fields of Spring entity class.


src/app/model/Artistes.ts


export class Artistes { _id: number; last_name: string; first_name: string; birth_data: string; }

src/app/model/Actor.ts


export class Actor { _id: number; role: string; }

src/app/model/Director.ts


export class Director { _id: number; }

src/app/model/Movie.ts


import {Actor} from './Actor'; import {Director} from './Director'; export class Movie { _id: number; title: string; genre: string; summary: string; country: string; actor: Actor; director[]: Director; }

Create Data Service

This service will use Angular HTTPClient to send HTTP requests. You can see that its functions includes CRUD operations and finder method.


service/artiste.service.ts


import { Injectable } from '@angular/core'; import {HttpClient} from '@angular/common/http'; import {Observable} from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ArtisteService { private baseUrl = "http://localhost:8080"; constructor(private http: HttpClient) { } findAllArtistes(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/findAllArtists`); } }

service/movie.service.ts


import { Injectable } from '@angular/core'; import {HttpClient} from '@angular/common/http'; import {Observable} from 'rxjs'; @Injectable({ providedIn: 'root' }) export class MovieService { private baseUrl = "http://localhost:8080"; constructor(private http: HttpClient) { } findAllMovies(): Observable<any[]> { return this.http.ge<any[]>(`${this.baseUrl}/findAllMovies`); } getMovieByDetails(id: string): Observable<any> { return this.http.get(`${this.baseUrl}/movie/details=${id}`); } findMovieId(): Observable<any> { return this.http.get(`${this.baseUrl}/movie/id`); } findMovieYear(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/movie/years`); } findMovieTitle(): Observable<any> { return this.http.get(`${this.baseUrl}/movie/title`); } findMovieDirectorID(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/movie/directoryId`); } findMovieActorsId(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/movie/actor/id`); } findMovieSearch(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/movie/search`); } findMovieBetweenYear(): Observable<any[]> { return this.http.get<any[]>(`${this.baseUrl}/movie/between/year`); } }

Create Angular Components

As you’ve known before, there are 4 components corresponding to 4 routes defined in AppRoutingModule.


$ ng generate component find-all-artistes
$ ng generate component find-all-movies
$ ng generate component movie-details
$ ng generate component query-movies

Find all artistes component

find-all-artistes.component.ts


import { Component, OnInit } from '@angular/core'; import { Artistes } from '../model/Artistes'; import { ArtisteService } from '../service/artiste.service'; @Component({ selector: 'app-find-all-artistes', templateUrl: './find-all-artistes.component.html', styleUrls: ['./find-all-artistes.component.scss'] }) export class FindAllArtistesComponent implements OnInit { artistes: Artistes[]; spinnerLoad = true; showTable = false; allNumber: number; p = 0; constructor(private artisteService: ArtisteService) { } ngOnInit() { this.artisteService.findAllArtistes().subscribe(data => { this.artistes = data; this.spinnerLoad = false; this.showTable = true; this.allNumber = this.artistes.length; }); } }

find-all-artistes.component.html


<div class="container"> <h2> <i class="fas fa-icons" style='font-size:48px;'></i> All artistes {{allNumber}}</h2><hr> <div class="loader" *ngIf="spinnerLoad"></div> <div *ngIf="showTable"> <table class="table table-hover table-bordered"> <tr> <th>ID</th> <th>Firstname</th> <th>Lastname</th> <th>Birthdate</th> </tr> <tr *ngFor="let art of artistes | paginate:{itemsPerPage: 6, currentPage:p} "> <td>{{art._id}}</td> <td>{{art.last_name}}</td> <td>{{art.first_name}}</td> <td>{{art.birth_date}}</td> </tr> </table> <div id="pagination"> <pagination-controls (pageChange)="p=$event"></pagination-controls> </div> </divv> </div>

Find all movies component

find-all-movies.component.ts


import { Component, OnInit } from '@angular/core'; import {Router} from '@angular/router'; import { MovieService } from '../service/movie.service'; @Component({ selector: 'app-find-all-movies', templateUrl: './find-all-movies.component.html', styleUrls: ['./find-all-movies.component.scss'], }) export class FindAllMoviesComponent implements OnInit { spinnerLoad = true; showTable = false; collection = []; allNumber: number; p = 0; constructor(private movieService: MovieService, private router: Router) {} ngOnInit() { this.movieService.findAllMovies().subscribe(data => { this.collection = data; this.spinnerLoad = false; this.showTable = true; this.allNumber = this.collection.length; }); } movieDetails(id: string) { this.router.navigate(['movieDetails/', id]); } }

find-all-movies.component.scss


<div class="container"> <h2><i class="fas fa-video" style='font-size:48px;'></i> All movies <span>{{allNumber}}</span> </h2><hr> <div class="loader" *ngIf="spinnerLoad"></div> <div *ngIf="showTable"> <table class="table table-hover table-bordered"> <thead> <tr> <th>ID</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> <th>Details</th> </tr> </thead> <tbody> <tr *ngFor="let item of collection | paginate:{itemsPerPage: 6, currentPage:p}"> <td>{{item._id}}</td> <td>{{item.title}}</td> <td>{{item.genre}}</td> <td>{{item.country}}</td> <td>{{item.year}}</td> <td title="More details"><button type="button" class="btn btn-primary" (click)="movieDetails(item._id)">Details</button></td> </tr> </tbody> </table> <div id="pagination"> <pagination-controls (pageChange)="p=$event"></pagination-controls> </div> </div> </div>

Movies details component

movie-details.component.ts


import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Movie } from '../model/Movie'; import { MovieService } from '../service/movie.service'; @Component({ selector: 'app-movie-details', templateUrl: './movie-details.component.html', styleUrls: ['./movie-details.component.scss'] }) export class MovieDetailsComponent implements OnInit { idMovie: string; movies: Movie[]; movie: Movie = new Movie(); constructor(private movieService: MovieService, private route: ActivatedRoute) { } ngOnInit() { this.idMovie = this.route.snapshot.params.idMovie; this.movieService.getMovieByDetails(this.idMovie).subscribe(data => { this.movies = data; this.movies.forEach(movie => { this.movie = movie; }); }); } }

movie-details.component.html


<div class="container"> <div class="jumbotron"> <h1 class="display-4" style="color:#8e9195; font-family: initial;"><i class='fas fa-skiing'></i> Movie details </h1> <hr> <br> <div class="row"> <div class="col-sm-4"> <div class="card text-dark bg-light"> <div class="card-header bg-dark text-center text-light"><h4> Summary </h4></div> <div class="card-body"> <div class="list-group"> <span *ngIf="movie.summary"> {{movie.summary}}</span> <span *ngIf="!movie.summary"> No summary </span> </div> </div> <div class="card-footer bg-secondary border-danger text-right"> <a href="#" class="btn btn-info btn-md">home</a> </div> </div> </div> <div class="col-md-8"> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Role</th> </tr> </thead> <tbody> <tr *ngFor="let s of movie.actors"> <td *ngIf="s.role">{{s.role}}</td> <td *ngIf="!s.role">No role</td> </tr> </tbody> </table> </div> </div> <br> <hr style="margin-top: 0px; border: 1px solid #F48989;"> </div> </div>

Queries movies component

query-movies.component.ts


import { Component, OnInit } from '@angular/core'; import { Movie } from '../model/Movie'; import { MovieService } from '../service/movie.service'; @Component({ selector: 'app-query-movies', templateUrl: './query-movies.component.html', styleUrls: ['./query-movies.component.scss'], }) export class QueryMoviesComponent implements OnInit { movieId: Movie = new Movie(); years: Movie[]; movieTitle: Movie = new Movie(); movieDirector: Movie[]; movieActorsId: Movie[]; movieSearch: Movie[]; movieBetween: Movie[]; constructor(private movieService: MovieService) {} ngOnInit() { this.movieService.findMovieTitle().subscribe((title) => { this.movieTitle = title; }); this.movieService.findMovieYear().subscribe((years) => { this.years = years; }); this.movieService.findMovieId().subscribe((id) => { this.movieId = id; }); this.movieService.findMovieDirectorID().subscribe((director) => { this.movieDirector = director; }); this.movieService.findMovieActorsId().subscribe((actors) => { this.movieActorsId = actors; }); this.movieService.findMovieSearch().subscribe((search) => { this.movieSearch = search; }); this.movieService.findMovieBetweenYear().subscribe((between) => { this.movieBetween = between; }); } }

query-movies.component.html


<div class="container"> <span>Afficher les infos sur le film dont l'id est 2 ?</span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Role</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of movieId.actors"> <td>{{ movieId._id }}</td> <td *ngIf="m.role">{{ m.role }}</td> <td>{{ movieId.title }}</td> <td>{{ movieId.genre }}</td> <td>{{ movieId.country }}</td> <td>{{ movieId.year }}</td> </tr> </tbody> </table> <hr/> <span>Lister ts les films produits en 1979 ? </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of years"> <td>{{ m._id }}</td> <td>{{ m.title }}</td> <td>{{ m.genre }}</td> <td>{{ m.country }}</td> <td>{{ m.year }}</td> </tr> </tbody> </table> <hr/> <span>Afficher les infos sur le film dont le title est "Alien" produit en 1979 ? </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of movieTitle.actors"> <td>{{ m._id }}</td> <td>{{ m.title }}</td> <td>{{ m.genre }}</td> <td>{{ m.country }}</td> <td>{{ m.year }}</td> </tr> </tbody> </table> <hr/> <span>Trouver tous les films produits par le director dont l'id est 4 ? </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of movieDirector"> <td>{{ m._id }}</td> <td>{{ m.title }}</td> <td>{{ m.genre }}</td> <td>{{ m.country }}</td> <td>{{ m.year }}</td> </tr> </tbody> </table> <hr/> <span>Trouver tous les films dont l'acteur dont l'id est 23 a joué denans ? </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody style="background: #00a8ff; color: #ffffff"> <tr> <td>No data</td> </tr> </tbody> </table> <hr/> <span>Tous les films dont le titre commence par "Re" ? </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of movieSearch"> <td>{{ m._id }}</td> <td>{{ m.title }}</td> <td>{{ m.genre }}</td> <td>{{ m.country }}</td> <td>{{ m.year }}</td> </tr> </tbody> </table> <hr/> <span>Tous les films produits après 200 et avent 2015 </span> <table class="table table-hover"> <thead class="thead-light"> <tr> <th>Id</th> <th>Title</th> <th>Genre</th> <th>Country</th> <th>Year</th> </tr> </thead> <tbody> <tr *ngFor="let m of movieBetween"> <td>{{ m._id }}</td> <td>{{ m.title }}</td> <td>{{ m.genre }}</td> <td>{{ m.country }}</td> <td>{{ m.year }}</td> </tr> </tbody> </table> <hr/> </div>

Add the AppRoutingModule

In Angular, the best practice is to load and configure the router in a separate, top-level module that is dedicated to routing and imported by the root AppModule.


By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app folder.


app-routing-module.ts


import { QueryMoviesComponent } from './query-movies/query-movies.component'; import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { FindAllMoviesComponent } from './find-all-movies/find-all-movies.component'; import { MovieDetailsComponent } from './movie-details/movie-details.component'; import { FindAllArtistesComponent } from './find-all-artistes/find-all-artistes.component'; const routes: Routes = [ {path: '', redirectTo: '/findAllArtistes', pathMatch: 'full'}, { path: 'findAllMovies', component: FindAllMoviesComponent }, { path: 'query-movies', component: QueryMoviesComponent }, { path: 'movieDetails/:idMovie', component: MovieDetailsComponent }, { path: 'findAllArtistes', component: FindAllArtistesComponent }, ]; @NgModule({ imports: [RouterModule. forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }


NgModules and JavaScript modules

The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are complementary module systems that you can use together to write your apps.


In JavaScript each file is a module and all objects defined in the file belong to that module. The module declares some objects to be public by marking them with the export key word. Other JavaScript modules use import statements to access public objects from other modules.


app-module.ts


import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { NgxPaginationModule } from 'ngx-pagination'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { MovieDetailsComponent } from './movie-details/movie-details.component'; import { FindAllMoviesComponent } from './find-all-movies/find-all-movies.component'; import { QueryMoviesComponent } from './query-movies/query-movies.component'; import { HttpClientModule } from '@angular/common/http'; import { FindAllArtistesComponent } from './find-all-artistes/find-all-artistes.component'; @NgModule({ declarations: [ AppComponent, MovieDetailsComponent, FindAllMoviesComponent, QueryMoviesComponent, FindAllArtistesComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, NgxPaginationModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Conclusion

Now we have an overview of Angular 10 + Spring Boot CRUD example when building a CRUD App.

We also take a look at client-server architecture for REST API using Spring Web MVC & We used Mongodb for Data, as well, we are going to continue with Angular 10 project structure for building a front-end app to make HTTP requests and consume responses.




Post a Comment

Previous Post Next Post


Follow us on facebook