Mục tiêu
Ứng dụng blog- nắm bắt được về các thao tác với HttpClient trong Angular.
Mô tả- Ứng dụng blog
Ứng dụng blog đơn giản
Hướng dẫn
Bước 1: Khởi tạo project với Angular CLI (nếu đã có project thì có thể bỏ qua)
Các bạn chạy lệnh npm i typescript@2.9.2 -D để cài đặt thư viện typescript nếu phiên bản hiện tại < 2.9.2
Bước 2: Khởi tạo một service tên là post, 3 component tên là blog, blog-detail, blog-edit, interface post
ng g s post
ng g c blog
ng g c blog-edit
ng g c blog-detail
ng g interface post
Bước 3: Thay phần template của component vừa tạo bằng đoạn code sau:
file blog.component.html:
<h2>Simple Blog</h2> <form [formGroup]="postForm" (ngSubmit)="onSubmit()"> <div> <label> Title <br> <input type="text" formControlName="title"> </label> </div> <div *ngIf="postForm.get('title').invalid && postForm.get('title').touched" style="color: red"> Title is required and min length is 10 </div> <div> <label> body <br> <textarea formControlName="body" cols="30" rows="10"></textarea> </label> </div> <div *ngIf="postForm.get('body').invalid && postForm.get('body').touched" style="color: red"> Body is required and min length is 10 </div> <button type="submit">Submit</button> </form> <ul> <li *ngFor="let post of postList; index as i"> <h3> <a [routerLink]="['/blog', post.id]"> Post Id: {{post.id}} - {{post.title}} </a> </h3> <a [routerLink]="['/blog', post.id, 'edit']">Edit</a> <button (click)="deletePost(i)">Delete</button> </li> </ul>
blog-detail.component.html:
<div *ngIf="post; else nothing"> <h4> {{post.title}} </h4> <p> {{post.body}} </p> </div> <ng-template #nothing> <p>Nothing to show</p> </ng-template>
blog-edit.component.html:
<form [formGroup]="postForm" (ngSubmit)="onSubmit()"> <div> <label> Title <br> <input type="text" formControlName="title"> </label> </div> <div *ngIf="postForm.get('title').invalid && postForm.get('title').touched" style="color: red"> Title is required and min length is 10 </div> <div> <label> body <br> <textarea formControlName="body" cols="30" rows="10"></textarea> </label> </div> <div *ngIf="postForm.get('body').invalid && postForm.get('body').touched" style="color: red"> Body is required and min length is 10 </div> <button type="submit">Submit</button> </form>
Bước 4: Code phần logic cho component
blog.component.ts:
import { Component, OnInit } from '@angular/core'; import { PostService } from '../post.service'; import { IPost } from '../post'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-blog', templateUrl: './blog.component.html', styleUrls: ['./blog.component.scss'] }) export class BlogComponent implements OnInit { postList: IPost[] = []; postForm: FormGroup; constructor( private postService: PostService, private fb: FormBuilder ) {} ngOnInit() { this.postForm = this.fb.group({ title: ['', [Validators.required, Validators.minLength(10)]], body: ['', [Validators.required, Validators.minLength(10)]], }); this.postService .getPosts() .subscribe(next => (this.postList = next), error => (this.postList = [])); } onSubmit() { if (this.postForm.valid) { const {value} = this.postForm; this.postService.createPost(value) .subscribe(next => { this.postList.unshift(next); this.postForm.reset({ title: '', body: '' }); }, error => console.log(error)); } } deletePost(i) { const post = this.postList[i]; this.postService.deletePost(post.id).subscribe(() => { this.postList = this.postList.filter(t => t.id !== post.id); }); } } blog-detail.component.ts import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { PostService } from '../post.service'; import { IPost } from '../post'; @Component({ selector: 'app-blog-detail', templateUrl: './blog-detail.component.html', styleUrls: ['./blog-detail.component.scss'] }) export class BlogDetailComponent implements OnInit { post: IPost; constructor( private route: ActivatedRoute, private postService: PostService ) {} ngOnInit() { const id = +this.route.snapshot.paramMap.get('id'); this.postService.getPostById(id).subscribe( next => (this.post = next), error => { console.log(error); this.post = null; } ); } }
blog-edit.component.ts:
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { IPost } from '../post'; import { PostService } from '../post.service'; @Component({ selector: 'app-blog-edit', templateUrl: './blog-edit.component.html', styleUrls: ['./blog-edit.component.scss'] }) export class BlogEditComponent implements OnInit { post: IPost; postForm: FormGroup; constructor( private route: ActivatedRoute, private postService: PostService, private fb: FormBuilder, private router: Router ) {} ngOnInit() { this.postForm = this.fb.group({ title: ['', [Validators.required, Validators.minLength(10)]], body: ['', [Validators.required, Validators.minLength(10)]] }); const id = +this.route.snapshot.paramMap.get('id'); this.postService.getPostById(id).subscribe( next => { this.post = next; this.postForm.patchValue(this.post); }, error => { console.log(error); this.post = null; } ); } onSubmit() { if (this.postForm.valid) { const { value } = this.postForm; const data = { ...this.post, ...value }; this.postService.updatePost(data).subscribe( next => { this.router.navigate(['/blog']); }, error => console.log(error) ); } } }
Bước 5: Cài đặt post service để call API:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { IPost } from './post'; @Injectable({ providedIn: 'root' }) export class PostService { private readonly API_URL = 'http://jsonplaceholder.typicode.com/posts'; constructor(private http: HttpClient) { } getPosts(count = 10): Observable<IPost[]> { return this.http.get<IPost[]>(this.API_URL).pipe( map(response => response.filter((post, i) => i < count)) ); } getPostById(id: number): Observable<IPost> { return this.http.get<IPost>(`${this.API_URL}/${id}`); } createPost(post: Partial<IPost>): Observable<IPost> { return this.http.post<IPost>(this.API_URL, post); } deletePost(id: number): Observable<any> { return this.http.delete(`${this.API_URL}/${id}`); } updatePost(post: IPost): Observable<IPost> { return this.http.patch<IPost>(`${this.API_URL}/${post.id}`, post); } }
Bước 6: Cài đặt post interface:
export interface IPost { userId: number; id: number; title: string; body: string; }
Bước 7: Tạo mới file app-routing.module.ts:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { BlogComponent } from './blog/blog.component'; import { BlogDetailComponent } from './blog-detail/blog-detail.component'; import { BlogEditComponent } from './blog-edit/blog-edit.component'; const routes: Routes = [{ path: 'blog', component: BlogComponent }, { path: 'blog/:id', component: BlogDetailComponent }, { path: 'blog/:id/edit', component: BlogEditComponent }]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {}
Bước 8: Thêm vào app.module.ts:
import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { BlogDetailComponent } from './blog-detail/blog-detail.component'; import { BlogComponent } from './blog/blog.component'; import { BlogEditComponent } from './blog-edit/blog-edit.component'; @NgModule({ declarations: [ AppComponent, BlogComponent, BlogDetailComponent, BlogEditComponent ], imports: [ BrowserModule, ReactiveFormsModule, HttpClientModule, AppRoutingModule ], bootstrap: [AppComponent] }) export class AppModule { }
Bước 9: Thêm vào app.component.html:
<nav> <a routerLink="/blog">Blog</a> </nav> <router-outlet></router-outlet>
Bước 10: Kiểm tra kết quả hiển thị trên trình duyệt localhost:4200/blog
User có thể click chuyển trang qua lại, có thể tạo mới post, có thể edit, delete post
Mã nguồn tham khảo: https://github.com/codegym-vn/angular-training/tree/master/angular-http/src/app
Trên đây CodeGym đã cùng với bạn luyện tập các thao tác với HttpClient trong Angular. Hãy chụp ảnh màn hình và nộp bài thực hành của bạn trên CodeGymX để cùng nhau luyện tập nhé!
0 Lời bình