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, chúng ta đã xây dựng giao diện của trang thêm mới option. Giờ là lúc chúng ta sẽ hiện chức năng thêm mới option này các bạn nhé!
Đầu tiên, mình sẽ tạo mới một class OptionsService để thực hiện việc gọi API thêm mới option từ API Option Service.
Để làm được điều này, mình sẽ tạo mới một class OptionsService nằm trong thư mục src/app/services như sau:
Class này sẽ được inject vào class NewOptionComponent để 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 OptionsService { } |
Để có thể gọi API thêm mới option của API Option 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 11 |
import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; @Injectable() export class OptionsService { constructor(private http: HttpClient) { } } |
Bây giờ thì mình có thể viết phương thức để thêm mới option từ API Option Service rồi:
1 2 3 |
addOption(option: Option) { return this.http.post("/option/add", JSON.stringify(option), { headers: this.headers }).toPromise(); } |
với biến headers được khai báo như sau:
1 |
private headers = new HttpHeaders({ 'Content-Type': 'application/json' }); |
Tương tự như khi gọi API Category Service và API Question 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 Option Service như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "/category/*": { "target": "http://localhost:8282", "secure": false, "logLevel": "debug" }, "/question/*": { "target": "http://localhost:8281", "secure": false, "logLevel": "debug" }, "/option/*": { "target": "http://localhost:8283", "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 “/option” sẽ được request tới địa chỉ http://localhost:8283, là địa chỉ của API Option Service đó các bạn!
Tương tự như class CategoriesService và QuestionsService, chúng ta cần khai báo class OptionsService 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 34 35 |
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'; import { OptionsService } from './services/options.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule, AppRoutingModule, NavigationModule, DashboardModule, QuestionsModule ], providers: [ CategoriesService, QuestionsService, OptionsService ], bootstrap: [ AppComponent ] }) export class AppModule { } |
OK, bây giờ chúng ta sẽ sử dụng class OptionsService để thực hiện việc thêm mới option 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 OptionsService trong phần constructor của class NewOptionComponent 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, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { OptionsService } from "../../services/options.service"; @Component({ selector: 'qm-body', templateUrl: './new_option.component.html' }) export class NewOptionComponent implements OnInit { questionId: string; constructor(private route: ActivatedRoute, private optionsService: OptionsService, private router: Router) { } ngOnInit(): void { this.questionId = this.route.snapshot.queryParamMap.get('questionId'); } } |
Như các bạn thấy, mình cũng đã khai báo thêm các đối tượng ActivatedRoute để lấy question id từ request URL và đối tượng Router để sau khi thêm mới option thành công, chúng ta sẽ redirect tới trang thông tin chi tiết của một question để kiểm tra kết quả.
Tiếp theo, chúng ta sẽ sửa form thêm mới option để thêm các biến lưu giữ giá trị của description, isCorrect, note mà người dùng nhập vào bằng cách sử dụng directive ngModel của Angular như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<form role="form"> <div class="form-group"> <label>Description</label> <textarea class="form-control" rows="3" name="description" [(ngModel)]="description"></textarea> <p class="help-block">The description of the option.</p> </div> <div class="form-group"> <label>Correct</label> <div class="checkbox"> <label> <input type="checkbox" name="isCorrect" [(ngModel)]="isCorrect">Correct ? </label> </div> </div> <div class="form-group"> <label>Note</label> <textarea class="form-control" rows="3" name="note" [(ngModel)]="note"></textarea> <p class="help-block">The note for the option.</p> </div> <button type="submit" class="btn btn-primary" (click)="createNewOption()">Add New Option</button> </form> |
Như các bạn thấy, mình cũng đã sửa lại nội dung của button “Add New Option” cho phép khi người dùng khi click vào button này thì ứng dụng của chúng ta sẽ gọi đến method createNewOption() trong class NewOptionComponent để thực hiện việc thêm mới option.
Nội dung của class NewOptionComponent sẽ được 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { Option } from "../../services/questions.service"; import { OptionsService } from "../../services/options.service"; @Component({ selector: 'qm-body', templateUrl: './new_option.component.html' }) export class NewOptionComponent implements OnInit { description: string; note: string; isCorrect: boolean; questionId: string; newOption: Option; constructor(private route: ActivatedRoute, private optionsService: OptionsService, private router: Router) { } ngOnInit(): void { this.questionId = this.route.snapshot.queryParamMap.get('questionId'); } createNewOption() { if (this.isEmpty(this.description)) { alert("Description cannot be empty."); return; } this.newOption = new Option(); this.newOption.description = this.description; this.newOption.note = this.note; this.newOption.isCorrect = this.isCorrect; this.newOption.questionId = this.questionId; this.optionsService.addOption(this.newOption) .then(o => { alert("Success"); this.router.navigate(['/question/' + this.questionId]); }) .catch(this.handleError); } isEmpty(val) { return val === undefined || val == null || val.length <= 0; } private handleError(error: any): Promise<any> { alert('An error occurred' + error); return Promise.reject(error.message || error); } } |
Như mình đã nói ở trên, sau khi thêm mới thành công option, ứng dụng của chúng ta sẽ redirect tới trang thông tin của question nên trong class NewOptionComponent trên, mình đã sử dụng phương thức navigate() của đối tượng Router để redirect tới URL “/question/{id}” sau khi nhận response thành công từ API Option Service.
OK, vậy là chúng ta đã hiện thực xong phần thêm mới option trong phần Frontend của ứng dụng Questions Management rồi đó các bạn. Thử test xem sao nhé!
Trong trang “Add New Option”, sau khi nhập thông tin về option cần thêm mới:
và nhấn nút “Add New Option”, ứng dụng của chúng ta sẽ tự redirect tới trang thông tin của question này như sau: