Xem toàn bộ series bài viết hướng dẫn xây dựng ứng dụng Questions Management tại đây.
Trong bài viết trước, mình đã xây dựng giao diện cho phần hiển thị tất cả các question rồi. Bây giờ là lúc chúng ta sẽ gọi các API của API Question Service để thực hiện các thao tác trên question các bạn nhé! Đầu tiên sẽ là hiển thị tất cả các question.
Đầu tiên, mình sẽ tạo mới một class QuestionsService để thực hiện việc gọi API lấy tất cả các question từ API Question Service.
Để làm được điều này, đầu tiên, mình sẽ tạo mới một class QuestionsService nằm trong thư mục src/app/services như sau:
Class này sẽ được inject vào class AllQuestionsComponent để sử dụng nên mình sẽ khai báo nó cùng với decorator @Injectable như sau:
1 2 3 4 5 6 |
import { Injectable } from "@angular/core"; @Injectable() export class QuestionsService { } |
Tiếp theo mình sẽ tạo mới các đối tượng để chứa các thông tin về question mà API Question Service sẽ trả về. Vì đối tượng chứa thông tin về category mình đã tạo trong bài viết trước rồi nên mình sẽ tạo thêm những đối tượng Question, Option, CompositeQuestion như sau:
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 |
import { Injectable } from "@angular/core"; @Injectable() export class QuestionsService { } export class Option { id: string; note: string; questionId: string; description: string; isCorrect: boolean; } export class Question { id: string; categoryId: string; description: string; } export class CompositeQuestion { id: string; category: Category; description: string; options: Option[]; } |
Để có thể gọi API lấy tất cả các question của API Question Service, mình sẽ khai báo sử dụng đối tượng HttpClient của Angular như sau:
1 2 3 4 5 6 7 8 9 10 |
import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; @Injectable() export class QuestionsService { constructor(private http: HttpClient) { } } |
Bây giờ thì mình có thể viết phương thức để lấy tất cả các question từ API Question Service rồi:
1 2 3 |
findAllQuestions(): Promise<CompositeQuestion[]> { return this.http.get<CompositeQuestion[]>("/question/all").toPromise(); } |
Tương tự như khi gọi API Category Service, để tránh lỗi CORS mà mình đã đề cập trong bài viết này, mình sẽ sửa tập tin proxy.conf.json nằm trong thư mục của project frontend để thêm cho phần gọi tới API Question Service như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "/category/*": { "target": "http://localhost:8282", "secure": false, "logLevel": "debug" }, "/question/*": { "target": "http://localhost:8281", "secure": false, "logLevel": "debug" } } |
Với khai báo trên, các request ra ngoài với URL bắt đầu bằng “/question” sẽ được request tới địa chỉ http://localhost:8281, là địa chỉ của API Question Service đó các bạn!
Tương tự như class CategoriesService, chúng ta cần khai báo class QuestionsService này trong class AppModule, trong thuộc tính provider của decorator @NgModule như sau:
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 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { NavigationModule } from './navigation/navigation.module'; import { DashboardModule } from './dashboard/dashboard.module'; import { AppRoutingModule } from './app-routing.module'; import { QuestionsModule } from './questions/questions.module'; import { CategoriesService } from './services/categories.service'; import { HttpClientModule } from '@angular/common/http'; import { QuestionsService } from './services/questions.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule, AppRoutingModule, NavigationModule, DashboardModule, QuestionsModule ], providers: [ CategoriesService, QuestionsService ], bootstrap: [ AppComponent ] }) export class AppModule { } |
OK, bây giờ chúng ta sẽ sử dụng class QuestionsService để lấy tất cả các question hiện có để display lên giao diện của phần hiển thị tất cả các câu hỏi các bạn nhé.
Để làm được điều này, đầu tiên, chúng ta sẽ khai báo sử dụng class QuestionsService trong phần constructor của class AllQuestionsComponent như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import { Component, AfterViewInit } from "../../../../node_modules/@angular/core"; import { QuestionsService, CompositeQuestion } from "../../services/questions.service"; declare var $: any; @Component({ selector: 'qm-body', templateUrl: './all_questions.component.html' }) export class AllQuestionsComponent implements AfterViewInit { constructor(private questionsService: QuestionsService) { } ngAfterViewInit(): void { $('#dataTables-questions').DataTable({ responsive: true }); } } |
Bây giờ thì chúng ta có thể viết code sử dụng phương thức findAllQuestions() của QuestionsService để lấy tất cả các question rồi:
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 |
import { Component, AfterViewInit } from "../../../../node_modules/@angular/core"; import { QuestionsService, CompositeQuestion } from "../../services/questions.service"; declare var $: any; @Component({ selector: 'qm-body', templateUrl: './all_questions.component.html' }) export class AllQuestionsComponent implements AfterViewInit { compositeQuestions: CompositeQuestion[]; constructor(private questionsService: QuestionsService) { } showAllQuestions() { this.questionsService.findAllQuestions().then(r => { this.compositeQuestions = r; setTimeout(function() { $('#dataTables-questions').DataTable({ responsive: true }); }, 100); }); } ngAfterViewInit(): void { this.showAllQuestions(); } } |
Để hiển thị những question này lên, trong tập tin all_questions.component.html, phần table hiển thị danh sách các question mình sẽ sửa lại như sau:
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 |
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-questions"> <thead> <tr> <th>Description</th> <th>Category</th> <th>Actions</th> <th>Options</th> </tr> </thead> <tbody> <tr *ngFor="let c of compositeQuestions; let odd = odd; let even = even" [ngClass]="{ odd: odd, even: even }"> <td>{{ c.description }}</td> <td>{{ c.category.name }}</td> <td> <button type="button" class="btn btn-primary btn-circle"><i class="fa fa-eye"></i></button> <button type="button" class="btn btn-warning btn-circle"><i class="fa fa-edit"></i></button> <button type="button" class="btn btn-danger btn-circle"><i class="fa fa-trash"></i></button> </td> <td> <button type="button" class="btn btn-success btn-circle"><i class="fa fa-plus"></i></button> </td> </tr> </tbody> </table> <!-- /.table-responsive --> |
OK, mọi thứ đã xong, giờ chạy thử nha các bạn.
Ở đây, chúng ta cần chạy ứng dụng Angular với tập tin proxy.conf.json như sau:
1 |
ng serve --proxy-config proxy.conf.json |
Giả sử lúc này trong database mình đang có những thông tin như sau:
thì lúc này, nếu chạy ứng dụng các bạn sẽ thấy danh sách các question được hiển thị như sau: