Quiz project with Spring boot & Angular Part 2

Getting Started | Building an Application with Angular




In this part 2 of quiz project we will create Angular project

The Angular CLI is a command-line interface tool used to initialize, develop, scaffold and maintain Angular applications.


This tool will create a new project that is ready to run immediately. It will create all needed plumbing to get everything up and running in a matter of minutes, generating an application structure that is based on best practices for an Angular project.


New elements will be created in a proper directory structure. Also, source code will be generated, plus in some cases, code will be added to other elements within the project so that the new elements can be used wherever needed.


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.


Open Command and tap this commands

1: Creating an Angular project with Angular CLI


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

2: Installing Bootstrap from NPM

npm install bootstrap


3: Alternative: Local Bootstrap CSS

       


/* You can add global styles to this file, and also import other style files */ @import '~bootstrap/dist/css/bootstrap.min.css'; html, body { height: 100%; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }

We want to create models for what standard objects and/or classes in our application should look like?


For those who have worked with MVC frameworks before, typically you declare types in a model which can then be reused throughout the rest of the application. With TypeScript, frontend applications can now benefit from strongly typed models!


While TypeScript has interfaces that can provide this functionality, the Angular team recommends just using a bare ES6 class with strongly typed instance variables for services or declarables (components, directives, and pipes) and Interfaces for data models.


First create a backage model in side it add a class Model.ts

model.ts

       


export enum Difficulty { easy, medium, hard } export class History { id: number; username: string; themeName: string; levelName: string; total: number; sore: number; } export interface Level { difficulty: Difficulty; id: number; themeName: string; } export interface Question { question: string; id: number; response1: string; response2: string; response3: string; correct: string; } export interface Response { response1: string; response2: string; response3: string; correct: string; } export interface Theme { id: number; name: string; } export class User { id: number; username: string; constructor(username: string) { this.username = username; } }

Add services

Components shouldn't fetch or save data directly and they certainly shouldn't knowingly present fake data. They should focus on presenting data and delegate data access to a service.


Services are a great way to share information among classes that don't know each other. You'll create a Service and inject it in two places.

1) first go to your Project Directory

2) then Run below Command in terminal.


ng g s service/history

ng g s service/level

ng g s service/question

ng g s service/response

ng g s service/theme

ng g s service/user

-> HistoryService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { History} from '../model/Model'; @Injectable({ providedIn: 'root' }) export class HistoryService { constructor(private http: HttpClient) { } public addHistory(history: History): Observable<History> { return this.http.post<History>(`http://localhost:8888/api/addHistory`, history); } public editHistory(history: History, username: string): Observable<History> { return this.http.put<History>(`http://localhost:8888/api/editHistory/${username}`, history); } public getHistories(): Observable<History[]> { return this.http.get<History[]>(`http://localhost:8888/api/getHistories`); } public findHistoryBySore(id: number): Observable<History> { return this.http.get<History>(`http://localhost:8888/api/findHistoryBySore/${id}`); } public findHistoryByUsername(username: string): Observable<History> { return this.http.get<History>(`http://localhost:8888/api/findHistoryByUsername/${username}`); } }

-> LevelService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { Level} from '../model/Model'; @Injectable({ providedIn: 'root' }) export class LevelService { constructor(private http: HttpClient) { } public addLevel(level: Level, idTheme: number): Observable<Level> { return this.http.post<Level>(`http://localhost:8888/api/addLevel/${idTheme}`, level); } public getLevels(idTheme: number): Observable<Level[]> { return this.http.get<Level[]>(`http://localhost:8888/api/getLevels/${idTheme}`); } public getLevel(id: number): Observable<Level> { return this.http.get<Level>(`http://localhost:8888/api/getLevel/${id}`); } }

-> QuestionService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { Question} from '../model/Model'; @Injectable({ providedIn: 'root' }) export class QuestionService { constructor(private http: HttpClient) { } public addQuestion(question: Question, idLevel: number): Observable<Question> { return this.http.post<Question>(`http://localhost:8888/api/addQuestion/${idLevel}`, question); } public getQuestions(idLevel: number): Observable<Question[]> { return this.http.get<Question[]>(`http://localhost:8888/api/getQuestions/${idLevel}`); } }

-> ResponseService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { Response} from '../model/Model'; @Injectable({ providedIn: 'root' }) export class QuestionService { constructor(private http: HttpClient) { } public addResponse(response: Response, idQuestion: number): Observable<Response> { return this.http.post<Response>(`http://localhost:8888/api/addResponse/${idQuestion}`, response); } public getResponses(idQuestion: number): Observable<Response[]> { return this.http.get<Response[]>(`http://localhost:8888/api/getResponses/${idQuestion}`); } }

-> ThemeService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { Theme} from '../model/Model'; @Injectable({ providedIn: 'root' }) export class ThemeService { constructor(private http: HttpClient) { } public addTheme(theme: Theme, idTheme: number): Observable<Theme> { return this.http.post<Theme>(`http://localhost:8888/api/addTheme/${idTheme}`, theme); } public getThemes(): Observable<Theme[]> { return this.http.get<Theme[]>(`http://localhost:8888/api/getThemes`); } public getTheme(id: number): Observable<Theme> { return this.http.get<Theme>(`http://localhost:8888/api/getTheme/${id}`); } }

-> UserService

       


import { Injectable} from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Observable} from 'rxjs'; import { User} from '../model/Model'; const USERNAME_KEY = 'AuthUsername'; @Injectable({ providedIn: 'root' }) export class QuestionService { constructor(private http: HttpClient) { } public saveUsername(username: string): void { window.sessionStorage.removeItem(USERNAME_KEY); window.sessionStorage.setItem(USERNAME_KEY, username); } public getUsername(): string { return sessionStorage.getItem(USERNAME_KEY); } }

Launching your app with App Component module

app.component.html

       


<div class="content"> <router-outlet> <router-outlet> <div>

app.component.css

       


html, body { height: 100%; margin: 0; } .content { background-color: #f7a400; height: 200vh; }

We need to create Header component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c header


header.component.html

       


<div class="row"> <div class="col-lg-2"> </div> <div class="col-lg-2"> <div class="card" style="width: 18rem; cursor: pointer;" routerLink="/home"> <img class="card-img-top img-thumbnail" src="https://media.discordapp.net/attachments/747757123055910982/747774704437166080/download.png" alt="Card image cap"> </div> </div> <div class="col-lg-4" style="position: relative;"> <h1 style="position: absolute; bottom: 80px; font-family: 'Alfa Slab One';font-size: 42px;"> Une seule réponse <br> est posible: </h1> </div> <div class="col-lg-2" id="loginBtn"> <button class="btn btn-primary btn-lg" style="background: #64379f !important; color: #fff; border: 0;">Créer un compte joueur</button> <button class="btn btn-primary btn-lg" style="background: #64379f !important; color: #fff; border: 0; margin-top: 5px;" routerLink="/home">Se connecter</button> </div> <br> </div>

We need to create Home component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c home

home.component.html

       


<br><br> <app-header></app-header> <br><br><br><br> <div class="row" id="add"> <div class="col-lg-2"></div> <div class="col-lg-4"> <div class="card"> <h2>Joueur</h2> <br> <form> <div class="form-group row"> <label for="name" class="col-sm-3 col-form-label">Nom de Joueur</label> <div class="col-sm-9"> <input type="text" class="form-control" name="userUsername" id="name" [(ngModel)]="userUsername"> </div> </div> <div class="btnContent"> <button type="submit" class="btn btn-primary" (click)="userLogin(userUsername)">Valider</button> </div> </form> </div> </div> <div class="col-lg-4"> <div class="card"> <h2>Admin</h2> <br> <form> <div class="form-group row"> <label for="adminUsername" class="col-sm-3 col-form-label">Nom de Admin</label> <div class="col-sm-9"> <input type="text" class="form-control" id="adminUsername" name="adminUsername" [(ngModel)]="adminUsername"> </div> </div> <div class="btnContent"> <button type="submit" class="btn btn-primary" (click)="adminLogin(adminUsername)">Valider</button> </div> </form> </div> </div> </div>

home.component.css

       


#add .card { padding: 20px; padding: 20px; background: #64379f; color: #fff; } #add h2 { text-align: center; margin-bottom: 20px; font-family: 'Aclonica'; } #add input { border-radius: 50px; } #add .btnContent { text-align: center; margin-top: 30px; } #add .btnContent .btn { padding: 4px 54px; border-radius: 50px; }

We need to create Question component to dispay Admin Home page

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c question

question.component.html

       


<div class="row"> <div class="col-lg-3"> <div id="sideBar"> <div class="card" style="width: 18rem; cursor: pointer; margin-left: 60px;" routerLink="/home"> <img class="card-img-top img-thumbnail" src="https://media.discordapp.net/attachments/747757123055910982/747774704437166080/download.png" alt="Card image cap"> </div> <h3 style="margin: 18px 0 -12px 15px;">Quizz</h3> <hr> <div style="padding: 16px;"> <div class="card" id="theme"> <div class="list-group"> <button type="button" class="list-group-item list-group-item-action active" style="cursor: default;">Thèmes</button> <button style="cursor: default" type="button" class="list-group-item d-flex justify-content-between list-group-item-action" *ngFor="let theme of themes"> <a [routerLink]="['/questions/level/', theme.id]">{{theme.name}} </a> <div> <i class="far fa-edit"></i> <i class='fas fa-trash-alt' style='color:red; margin: 0 12px'></i> <i class="fas fa-plus-square" (click)="addLevel(theme.id)"></i> </div> </button> <button type="button" class="list-group-item list-group-item-action active" style="text-align: center;" (click)="openRegister()">Ajouter un thème </button> </div> </div> </div> <button type="button" class="btn btn-outline-danger" style="margin-left: 20px;" routerLink="/home">Deconnecter</button> </div> </div> <div class="col-lg-9"> <router-outlet></router-outlet> </div> </div>

question.component.css

       


html, body { height: 100%; margin: 0; } #sideBar { height: 100vh; background-color: aliceblue; padding-top: 40px; } h1 { background: #64379f; margin-left: -30px; text-align: center; padding: 10px; color: aliceblue; }

question.component.ts

       


import {AddThemeComponent} from './../add-theme/add-theme.component'; import {Component, OnInit} from '@angular/core'; import {MatDialog } from '@angular/material/dialog'; import {Theme} from '../model/Theme'; import {ThemeService} from '../service/theme.service'; import {AddLevelComponent} from '../level/add-level/add-level.component'; @Component({ selector: 'app-questions', templateUrl: './questions.component.html', styleUrls: ['./questions.component.css'] }) export class QuestionsComponent implements OnInit { dialogRef: any; themes: Theme[]; constructor(private dialog: MatDialog, private themeService: ThemeService) {} ngOnInit(): void { this.themeService.getThemes().subscribe(themes => { this.themes = themes; }); } openRegister(): void { this.dialogRef = this.dialog.open(AddThemeComponent, { width: '420px' }); } addLevel(id: number): void { this.dialogRef = this.dialog.open(AddLevelComponent, { width: '420px', data: {id} }); } }

We need to create Welcome Admin component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c welcome

welcome.component.html

       


<h1 style="border-bottom: 6px solid #fff;">Welcome : Admin </h1> <h2> Please choice a level </h2> <img src="https://www.espacil-habitat.fr/wp-content/uploads/2019/04/126-961x550.jpg" alt="Welcome image">

We need to create Add Theme component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c addTheme

add-theme.component.html

       


<div id="add"> <div class="card"> <h2> Créer un theme</h2> <br> <form (ngSubmit)="addTheme()"> <div class="form-group row"> <div class="col-sm-9"> <input type="text" name="name" [(ngModel)]="theme.name" class="form-control" id="name" placeholder="Enter theme nom"> </div> </div> <div class="btnContent" style="display: grid;"> <button type="submit" class="btn btn-primary">Valider</button> </div> </form> </div> </div>

add-theme.component.css

       


#add .card { padding: 20px; padding: 20px; background: #64379f; color: #fff; } #add h2 { text-align: center; margin-bottom: 20px; font-family: "Aclonica"; } #add input { border-radius: 50px; }

add-theme.component.ts

       


import {Component, OnInit} from '@angular/core'; import {Theme} from '../model/Model'; import {ThemeService} from '../service/theme.service'; @Component({ selector: 'app-add-theme', templateUrl: './add-theme.component.html', styleUrls: ['./add-theme.component.css'] }) export class AddThemeComponent implements OnInit { theme: Theme = {} as Theme; constructor(private themeService: ThemeService) { } ngOnInit(): void { } addTheme(): void { this.themeService.addTheme(this.theme).subscribe(theme => { this.theme = theme; window.location.reload(); }); } }

We need to create Add Level component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c addLevel

add-level.component.html

       


<div id="add"> <div class="card"> <h2> Créer un difficulty </h2> <br> <form (ngSubmit)="addLevel()"> <div class="form-group row"> <div class="col-sm-9"> <input type="text" name="difficulty" [(ngModel)]="level.difficulty" class="form-control" id="name" placeholder="Difficulty"> </div> </div> <div class="btnContent" style="display: grid;"> <button type="submit" class="btn btn-primary">Valider</button> </div> </form> </div> </div>

add-level.component.ts

       


import {Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Level} from '../model/Model'; import {LevelService} from '../service/level.service'; @Component({ selector: 'app-add-level', templateUrl: './add-level.component.html', styleUrls: ['./add-level.component.css'] }) export class AddLevelComponent implements OnInit { level: Level = {} as Level; constructor(public dialogRef: MatDialogRef<AddLevelComponent>, @Inject(MAT_DIALOG_DATA) private data: any, private levelService: LevelService) { } ngOnInit(): void { } addLevel(): void { this.levelService.addLevel(this.level, this.data.id).subscribe(level => { this.level = level; window.location.reload(); }); } }

We need to create Level component to display difficulty

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c level

level.component.html

       


<h1 style="border-bottom: 6px solid #fff; background: #64379f; margin-left: -30px; text-align: center; padding: 10px; color: aliceblue;">Level : JAVA</h1> <div class="row"> <div class="col-lg-4"> <div class="card"> <div class="list-group"> <button type="button" class="list-group-item list-group-item-action active" style="cursor: default;">Difficulty</button> <button type="button" class="list-group-item d-flex justify-content-between list-group-item-action" *ngFor="let level of levels" style="cursor: default"> <a [routerLink]="['/questions/level/' + idTheme + '/questionContent/' + level.id]">{{level.difficulty}}</a> <div> <i class="far fa-edit"></i> <i class='fas fa-trash-alt' style='color:red; margin: 0 12px'></i> <button type="button" class="btn btn-link" (click)="openRegister(level.id)">Add question</button> </div> </button> </div> </div> </div> <div class="col-lg-8"> <router-outlet></router-outlet> </div> </div>

level.component.ts

       


import {Component, OnInit} from '@angular/core'; import {Level} from '../model/Model'; import {LevelService} from '../service/level.service'; import {ActivatedRoute} from '@angular/router'; import {AddQuestionComponent} from '../add-question/add-question.component'; import {MatDialog} from '@angular/material/dialog'; @Component({ selector: 'app-level', templateUrl: './level.component.html', styleUrls: ['./level.component.css'] }) export class LevelComponent implements OnInit { levels: Level[]; idTheme: number; dialogRef: any; constructor(private levelService: LevelService, private route: ActivatedRoute, private dialog: MatDialog) { this.route.params.subscribe( params => { this.idTheme = this.route.snapshot.params.id; this.levelService.getLevels(this.idTheme).subscribe(levels => { this.levels = levels; }); } ); } ngOnInit(): void { } public openRegister(id: number): void { this.dialogRef = this.dialog.open(AddQuestionComponent, { width: '500px', data: {id} }); } }

We need to create AddQuestion component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c add-question

add-question.component.html

       


<div class="card addQuestion"> <h2 style="margin-bottom: 30px;">Créer une question </h2> <br><br> <from (ngSubmit)="addQuestion()"> <div class="form-group row"> <label for="name" class="col-sm-3 col-form-label">Question</label> <div class="col-sm-9"> <input type="text" class="form-control" id="name" [(ngModel)]="question.question" name="name"> </div> </div> <fieldset class="form-group" id="response"> <div class="row"> <legend class="col-form-label col-sm-4 pt-0">Cochez = vraie</legend> <mat-radio-group aria-label="Select an option" [(ngModel)]="correct" name="gender" (ngModelChange)="setResponse()"> <mat-radio-button value="{{question.response1}}" style="margin-left: 10px;"> <input type="text" class="form-control form-control-md" [(ngModel)]="question.response1" name="response1" placeholder="Résponse 1"> </mat-radio-button> <br> <mat-radio-button value="{{question.response2}}" style="margin-left: 10px;"> <input type="text" class="form-control form-control-md" [(ngModel)]="question.response2" name="response2" placeholder="Résponse 2"> </mat-radio-button> <br> <mat-radio-button value="{{question.response3}}" style="margin-left: 10px;"> <input type="text" class="form-control form-control-md" [(ngModel)]="question.response3" name="response3" placeholder="Résponse 3"> </mat-radio-button> <br> </mat-radio-group> </div> </fieldset> <div class="btnContent"> <button type="submit" class="btn btn-primary" style="margin-right: 5px">Valider </button> </div> </from> <button type="button" class="btn btn-danger" style="margin-right: 5px" (click)="cancel()">Cancel </button> </div>

add-question.component.css

       


.addQuestion { background: #64379f; color: #ffffff; margin: 0 !important; padding: 15px; } #response input { padding: 10px !important; border-radius: 50px; margin-bottom: 5px; } .btnContent { float: right; margin-right: 34px; } .btnContent .btn { padding: 4px 20px; border-radius: 50px; }

add-question.component.ts

       


import { Component, Inject, OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog'; import { QuestionService } from '../service/question.service'; import { Question } from '../model/Model'; @Component({ selector: 'app-add-question', templateUrl: './add-question.component.html', styleUrls: ['./add-question.component.css'], }) export class AddQuestionComponent implements OnInit { question: Question = {} as Question; correct: any = {}; constructor(private dialog: MatDialog, private questionService: QuestionService, @Inject(MAT_DIALOG_DATA) private data: any) {} ngOnInit(): void { } cancel(): void { this.dialog.closeAll(); } setResponse(): void { this.question.correct = this.correct; } addQuestion(): void { this.questionService.addQuestion(this.question, this.data.id).subscribe((question) => { this.question = question; window.location.reload(); }); } }

We need to create QuestionContent component to display the questions

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c question-content

question-content.component.html

       


<div style="margin-right: 10px;"> <div class="card"> <div class="list-group"> <button type="button" class="list-group-item list-group-item-action active" style="cursor: default;">Questions</button> </div> </div> <mat-accordion> <mat-expansion-panel *ngFor="let q of questions, let i = index"> <mat-expansion-panel-header (click)="findResponse(q.id)"> <mat-panel-title> {{i+1}} </mat-panel-title> <mat-panel-description> {{q.question}} </mat-panel-description> </mat-expansion-panel-header> <div> <p style="color: red">{{q?.response1}}</p> <p style="color: red">{{q?.response2}}</p> <p style="color: red">{{q?.response3}}</p> <p *ngIf="q.correct==q?.response1" style="color: olivedrab">Correct réponse: {{q?.response1}}</p> <p *ngIf="q.correct==q?.response2" style="color: olivedrab">Correct réponse: {{q?.response2}}</p> <p *ngIf="q.correct==q?.response3" style="color: olivedrab">Correct réponse: {{q?.response3}}</p> </div> </mat-expansion-panel> </mat-accordion> </div>

question-content.component.ts

       


import {Component, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {Question} from '../model/Model'; import {QuestionService} from '../service/question.service'; import {ActivatedRoute} from '@angular/router'; import {Response} from '../model/Model'; import {ResponseService} from '../service/response.service'; @Component({ selector: 'app-question-content', templateUrl: './question-content.component.html', styleUrls: ['./question-content.component.css'] }) export class QuestionContentComponent implements OnInit { questions: Question[]; responses: Response[]; dialogRef: any; id: number; constructor(private dialog: MatDialog, private questionService: QuestionService, private route: ActivatedRoute, private responseService: ResponseService) { this.route.params.subscribe( params => { this.id = this.route.snapshot.params.id; this.questionService.getQuestions(this.id).subscribe(questions => { this.questions = questions; }); } ); } ngOnInit(): void { } findResponse(id: number): void { this.responseService.getResponses(id).subscribe(res => { this.responses = res; }); } }

We need to create Historique component to display the histories

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c historique

historique.component.html

       


<br> <br> <app-header></app-header> <br> <br> <br> <br> <div class="container"> <div class="card"> <table class="table"> <thead> <tr> <th scope="col">Nom du joueur</th> <th scope="col">Difficulté</th> <th scope="col">Thème</th> <th scope="col">Temps total</th> <th scope="col">Score</th> </tr> </thead> <tbody *ngFor="let h of histories"> <tr> <td> {{h.username}} </td> <td> {{h.levelName}}</td> <td> {{h.themeName}}</td> <td> {{h.total}}</td> <td> {{h.sore}}</td> </tr> </tbody> </table> </div> <div> <button class="btn btn-primary" [routerLink]="['/theme']" style="background: #3a9efd; margin-top: 15px; border-color: #3a9efd;">Commoncer le quizz</button> </div> </div>

historique.component.css

       


.card { background-color: #64379f; padding: 16px; color: #ffffff; } th { border: 0; color: #ffffff; } td { background: aliceblue; border-top: 6px solid #64379f; padding: 5px 15px; }

historique.component.ts

       


import {Component, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {HistoryService} from '../service/history.service'; import {History} from '../model/Model'; import {ActivatedRoute} from '@angular/router'; @Component({ selector: 'app-historique', templateUrl: './historique.component.html', styleUrls: ['./historique.component.css'] }) export class HistoriqueComponent implements OnInit { userUsername: string; dialogRef: any; histories: History[]; constructor(private dialog: MatDialog, private historyService: HistoryService, private route: ActivatedRoute) {} ngOnInit(): void { this.userUsername = this.route.snapshot.params.userUsername; this.historyService.getHistories().subscribe(histories => { this.histories = histories; }); } }

We need to create Theme component to display the list of quiz for user

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c themme

Theme.component.html

       


<div class="row"> <div class="col-lg-3"> <div id="sideBar"> <div class="card" style="width: 18rem; cursor: pointer; margin-left: 60px;" routerLink="/home"> <img class="card-img-top img-thumbnail" src="https://media.discordapp.net/attachments/747757123055910982/747774704437166080/download.png" alt="Card image cap"> </div> <h3 style="margin: 18px 0 -12px 15px;">Thèmes</h3> <hr> <div style="padding: 16px;" *ngFor="let t of themes"> <div class="card" id="theme"> <h4> {{t.name}}</h4> <button class="btn btn-danger" style="background: #3a9efd; border: 0;" (click)="openLevel(t.id, t.name)">GO! </button> </div> </div> <button type="button" class="btn btn-outline-danger" style="margin-left: 20px;">Deconnecter</button> </div> </div> <div class="col-lg-9"> <router-outlet></router-outlet> </div> </div>

theme.component.ts

       


html, body { height: 100%; margin: 0; } #sideBar { height: 200vh; background-color: aliceblue; padding-top: 40px; } h1 { background: #64379f; margin-left: -30px; text-align: center; padding: 10px; color: aliceblue; } #theme { background: #27104e; padding: 20px; text-align: center; color: aliceblue; } #difficulty { background-color: #3a9efd; }

theme.component.ts

       


import {MatDialog} from '@angular/material/dialog'; import {ThemeContentComponent} from './../theme-content/theme-content.component'; import {Component, OnInit} from '@angular/core'; import {Theme} from '../model/Model'; import {ThemeService} from '../service/theme.service'; import {ActivatedRoute} from '@angular/router'; @Component({ selector: 'app-theme', templateUrl: './theme.component.html', styleUrls: ['./theme.component.css'] }) export class ThemeComponent implements OnInit { themes: Theme[]; userUsername: string; dialogRef: any; constructor(private themeService: ThemeService, private route: ActivatedRoute, private dialog: MatDialog) { } ngOnInit(): void { this.userUsername = this. route.snapshot.params.userUsername; this. themeService.getThemes().subscribe(themes => { this.themes = themes; }); } openLevel(id, themeName): void { this.dialogRef = this.dialog.open(ThemeContentComponent, { width: '420px', data: {id, themeName} }); } }

We need to create ThemeContent component to display the level

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c themeContent

theme-content.component.html

       


<h1 style="border-bottom: 6px solid #fff;"> Thème {{themeName}} </h1> <div style="text-align: center;"> <button class="btn btn-danger" style="background: #64379f; border: 0;"> <h4> Allez "{{userName}}" !</h4> </button> </div> <div style="padding: 16px;" > <div class="card" id="difficulty" style="width: 20rem;"> <h4> Choissiez votre difficulté</h4> <mat-radio-group aria-label="Select an option" [(ngModel)]="level" name="gender" (ngModelChange)="setLevel($event)"> <mat-radio-button value="{{l.id}}" style="margin-left: 10px;" *ngFor="let l of levels">{{l.difficulty}} </mat-radio-button><br> </mat-radio-group> <br> <button type="button" class="btn btn-primary" [disabled]="idLevel === undefined" style="background: #64379f; margin-top: 15px;" (click)="openQuizz(idLevel)">Demarrez le quizz</button> </div> </div>

theme-content.component.css

       


h1 { background: #64379f; text-align: center; padding: 10px; color: aliceblue; } #difficulty { background-color: #3a9efd; padding: 20px; }

We need to create Quiz component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c home

quiz.component.html

       


<div class="row" id="header" style="border-bottom: 6px solid #fff;"> <div class="col-lg-10"> <h1> Thème: {{level.themeName}} - Niveau {{level.difficulty}}</h1> </div> <div class="col-lg-2"> <div id="time"> {{counter}}s </div> </div> </div> <div class="row"> <div class="col-lg-7"> <button class="btn btn-danger" style="background: #64379f; border: 0; margin-top: 10px;"> <h4> Allez "{{username}}" !</h4> </button> </div> <div class="col-lg-5"> <h3 style="margin-top: 10px;"> Cochez la bon réponse</h3> </div> </div> <div style="padding: 16px;" *ngFor="let q of questions"> <div class="card" id="quizz" style="width: 70rem;"> <h4> {{q.question}} ...?</h4> <mat-radio-group aria-label="Select an option" (change)="setResponses($event)"> <mat-radio-button [value]="q.response1"> {{q.response1}}</mat-radio-button> <br> <mat-radio-button [value]="q.response2"> {{q.response2}}</mat-radio-button> <br> <mat-radio-button [value]="q.response3"> {{q.response3}}</mat-radio-button> </mat-radio-group> </div> </div> <div style="text-align: center;"> <button class="btn btn-danger" [disabled]="btnDisabled" style="background: #27104e; border: 0; margin-top: 10px;" (click)="openResult(level.themeName, level.difficulty)"> <h4> Valider le quizz</h4> </button> <br><br> </div>

quiz.component.css

       


h1 { text-align: center; padding: 10px; color: aliceblue; } #time { background: #27104e; color: blanchedalmond; width: 50px; height: 50px; border-radius: 50px; padding: 10px 2px 12px 0; display: inline-block; text-align: center; margin-top: 10px; } #header { background: #64379f; margin-left: -30px; } #quizz { background: #64379f; padding: 16px; color: aliceblue; }

quiz.component.ts

       


import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Question } from '../model/Model'; import { QuestionService } from '../service/question.service'; import { ActivatedRoute } from '@angular/router'; import { timer } from 'rxjs'; import { ResultComponent } from '../result/result.component'; import { LevelService } from '../service/level.service'; import { HistoryService } from '../service/history.service'; import { History } from '../model/Model'; import { UserService } from '../service/user.service'; const counterSecond = timer(0, 1000); @Component({ selector: 'app-quizz', templateUrl: './quizz.component.html', styleUrls: ['./quizz.component.css'], }) export class QuizzComponent implements OnInit { dialogRef: any; questions: Question[]; history: History = {} as History; histories: History[]; idLevel: number; level: any; counter = 0; score = 0; btnDisabled = true; username: string; constructor( private dialog: MatDialog, private questionService: QuestionService, private route: ActivatedRoute, private levelService: LevelService, private historyService: HistoryService, private userService: UserService ) {} ngOnInit(): void { this.username = this.userService.getUsername(); this.idLevel = this.route.snapshot.params.idLevel; this.questionService.getQuestions(this.idLevel).subscribe((data) => { this.questions = data; for (var i = this.questions.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = this.questions[i]; this.questions[i] = this.questions[j]; this.questions[j] = temp; } }); this.levelService.getLevel(this.idLevel).subscribe((level) => { this.level = level; }); counterSecond.subscribe(() => { this.counter += 1; }); } openResult(themeName: any, levelName: any): void { const counter = this.counter; const score = this.score; const username = this.username; this.history.total = this.counter; this.history.themeName = themeName; this.history.levelName = levelName; this.history.username = username; this.history.sore = this.score; this.historyService.addHistory(this.history).subscribe((addHistory) => { this.history = addHistory; console.log(this.history); }); counterSecond.subscribe(() => { this.counter = +''; }); this.dialogRef = this.dialog.open(ResultComponent, { width: '420px', data: { score, counter, themeName, levelName }, }); } setResponses(e: any): void { this.questions.forEach((q, index) => { if (e.source.value === q.correct) { this.score++; } }); this.btnDisabled = false; } }

We need to create Result component

1) first go to your Project Directory

2) then Run below Command in terminal.

ng g c result

result.component.html

       


<div class="card" style="background: #3a9efd; padding: 15px; text-align: center;"> <p> Résultat: </p> <p> Score: {{score}} </p> <p> Temps: {{counter}}: sec </p> </div> <div style="margin-top: 10px;"> <button class="btn btn-danger" routerLink="/home" (click)="dismissPanel()">Quit</button> <button class="btn btn-success" routerLink="/theme" (click)="dismissPanel()" style="margin: 0 8px;">Continuer</button> <button class="btn btn-primary" [routerLink]="['/historiated/', username]" (click)="dismissPanel()">Histtorique</button> </div>

result.component.ts

       


import {UserService} from './../service/user.service'; import {Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialog} from '@angular/material/dialog'; @Component({ selector: 'app-result', templateUrl: './result.component.html', styleUrls: ['./result.component.css'] }) export class ResultComponent implements OnInit { counter = 0; score = 0; themeName: string; levelName: string; username = ''; constructor(private dialog: MatDialog, @Inject(MAT_DIALOG_DATA) private data: any, private userService: UserService) { } ngOnInit(): void { this.username = this.userService.getUsername(); this.counter = this.data.counter; this.score = this.data.score; this.levelName = this.data.levelName; this.themeName = this.data.themeName; } dismissPanel(): void { this.dialog.closeAll(); } }

app-routing-module.component.ts

       


import { WelcomeComponent } from './welcome/welcome.component'; import { ThemeContentComponent } from './theme-content/theme-content.component'; import { ThemeComponent } from './theme/theme.component'; import { QuizzComponent } from './quizz/quizz.component'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HistoriqueComponent } from './historique/historique.component'; import { HomeComponent } from './home/home.component'; import { QuestionsComponent} from './questions/questions.component'; import { QuestionContentComponent } from './question-content/question-content.component'; import { LevelComponent } from './level/level.component'; const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'historiated/:userUsername', component: HistoriqueComponent }, { path: 'theme', component: ThemeComponent, children: [ { path: 'quizz/:idLevel', component: QuizzComponent }, { path: 'themeContent/:id', component: ThemeContentComponent }, { path: '', component: WelcomeComponent }, ], }, { path: 'questions', component: QuestionsComponent, children: [ { path: '', component: WelcomeComponent }, { path: 'level/:id', component: LevelComponent, children: [ { path: 'questionContent/:id', component: QuestionContentComponent }, ], }, ], }, ]; @NgModule({ declarations: [], imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}

app.module.ts

       


import { BrowserModule } from '@angular/platform-browser'; import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; import { MatDialogModule} from '@angular/material/dialog'; import { AppComponent} from './app.component'; import { AddQuestionComponent } from './add-question/add-question.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { HistoriqueComponent } from './historique/historique.component'; import { AppRoutingModule } from './app-routing.module'; import { HomeComponent } from './home/home.component'; import { HeaderComponent } from './header/header.component'; import { QuizzComponent } from './quizz/quizz.component'; import { ThemeComponent } from './theme/theme.component'; import { ThemeContentComponent } from './theme-content/theme-content.component'; import { WelcomeComponent } from './welcome/welcome.component'; import { ResultComponent } from './result/result.component'; import { QuestionsComponent } from './questions/questions.component'; import { QuestionContentComponent } from './question-content/question-content.component'; import { AddThemeComponent } from './add-theme/add-theme.component'; import { FormsModule} from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { LevelComponent } from './level/level.component'; import { AddLevelComponent } from './add-level/add-level.component'; import { MatRadioModule } from '@angular/material/radio'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatIconModule } from '@angular/material/icon'; import { MatFormFieldModule } from '@angular/material/form-field'; @NgModule({ declarations: [ AppComponent, AddQuestionComponent, HistoriqueComponent, HomeComponent, HeaderComponent, QuizzComponent, ThemeComponent, ThemeContentComponent, WelcomeComponent, ResultComponent, QuestionsComponent, QuestionContentComponent, AddThemeComponent, LevelComponent, AddLevelComponent ], imports: [ BrowserModule, MatDialogModule, BrowserAnimationsModule, AppRoutingModule, BrowserModule, HttpClientModule, FormsModule, MatRadioModule, MatExpansionModule, MatIconModule, MatFormFieldModule ], schemas: [ CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, ], entryComponents: [ AddQuestionComponent, AddThemeComponent ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Now Run Application

ng serve


Conclusion

Now we have an overview of 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 & Spring Data JPA, as well, we ware creating 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