Trang chủ » Blog » [Thực hành] Ứng dụng blog- Codegym.vn

[Thực hành] Ứng dụng blog- Codegym.vn

bởi CodeGym | 26/12/2023 17:16 | Bài thực hành | Blog

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é!

Tags:

0 Lời bình

Gửi Lời bình

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

BÀI VIẾT LIÊN QUAN

BẠN MUỐN HỌC LẬP TRÌNH?

GỌI NGAY

098 953 44 58

Đăng ký tư vấn lộ trình học lập trình

Đăng ký tư vấn, định hướng lộ trình học và giải đáp các thắc mắc về ngành nghề – Miễn phí – Online.

10 + 3 =

TƯ VẤN VỀ LỘ TRÌNH HỌC NGHỀ LẬP TRÌNH TẠI CODEGYM
TƯ VẤN VỀ LỘ TRÌNH HỌC NGHỀ LẬP TRÌNH TẠI CODEGYM