Angular HttpClient module is the Angular version of making http request and handle the responses
List of Contents
Configurations
First we need to add HttpClientModule in the app.module file
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CommentComponent } from './components/comment/comment.component';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [AppComponent, CommentComponent],
imports: [BrowserModule, AppRoutingModule, HttpClientModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Services and models are not needed for this implementation. But for convenience purposes, we will add a service and a model
ng g s services/comment
ng g i models/comment
※ TypeScript is a strongly typed language, so you have specify a type whenever you create a variable or return a value. Model spares us the pain of specifying types by allowing us use the model as a type
To be more realistic, we will add components rather than using the app component along
ng g c components/comment
ng g c components/comment/comment-add
ng g c components/comment/comment-edit
Then add routing
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CommentAddComponent } from './components/comment/comment-add/comment-add.component';
import { CommentEditComponent } from './components/comment/comment-edit/comment-edit.component';
import { CommentComponent } from './components/comment/comment.component';
const routes: Routes = [
{ path: 'comment-add', component: CommentAddComponent },
{ path: 'comment-edit/:id', component: CommentEditComponent },
{ path: '', component: CommentComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
※ API
JSONPlaceholder - Free Fake REST API (typicode.com)
JSONPlaceholder - Free Fake REST API
{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB. Tested with XV. As of Oct 2022, serving ~1.7 billion requests each month.
jsonplaceholder.typicode.com
How to Use?
1. GET
Inject the HttpClient in the service file and create a get request as shown below
// comment.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Comment } from '../models/comment';
@Injectable({
providedIn: 'root'
})
export class CommentService {
URL = 'https://jsonplaceholder.typicode.com/comments/'
constructor(private http:HttpClient) { }
getComments():Observable<Comment[]> {
return this.http.get<Comment[]>(this.URL)
}
}
Then go to the component class that will request the data. Inject the service and call the get method
// comment.component.ts
import { Component, OnInit } from '@angular/core';
import { Comment } from 'src/app/models/comment';
import { CommentService } from 'src/app/services/comment.service';
@Component({
selector: 'app-comment',
templateUrl: './comment.component.html',
styleUrls: ['./comment.component.css'],
})
export class CommentComponent implements OnInit {
comments: Comment[] = [];
constructor(private commentService: CommentService) {}
ngOnInit(): void {
this.commentService.getComments().subscribe((comments) => {
this.comments = comments;
});
}
}
Let's show the data in the screen. Go to the template file and add the code below
<!-- comment.component.html -->
<div class="container">
<div class="card" style="display: flex; flex-direction: column; justify-content: space-around; height: 150px; width: 600px; font-family: Arial, Helvetica, sans-serif; padding: 10px; background-color: antiquewhite; margin: 10px auto;" *ngFor="let i of comments">
<p>{{i.id}}</p>
<p>{{i.body}}</p>
<div>
<p>{{i.name}}</p>
<p>{{i.email}}</p>
</div>
</div>
</div>
2. POST
Next, let's try to add an item. Add the 'addComment' function in the service
// comment.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Comment } from '../models/comment';
@Injectable({
providedIn: 'root',
})
export class CommentService {
URL = 'https://jsonplaceholder.typicode.com/comments/';
constructor(private http: HttpClient) {}
getComments(): Observable<Comment[]> {
return this.http.get<Comment[]>(this.URL);
}
addComment(body: string, name: string, email: string) {
const comment: Comment = {
body: body,
email: email,
name: name,
};
this.http.post(this.URL, comment).subscribe(result => {
console.log(result)
});
}
}
Create a function to handle the form submission and call the function from the service in the 'comment-add' component class.
// Comment-add.component.ts
import { Component, OnInit } from '@angular/core';
import { CommentService } from 'src/app/services/comment.service';
@Component({
selector: 'app-comment-add',
templateUrl: './comment-add.component.html',
styleUrls: ['./comment-add.component.css'],
})
export class CommentAddComponent implements OnInit {
constructor(private commentService: CommentService) {}
ngOnInit(): void {}
onSubmit(name: string, email: string, body: string) {
this.commentService.addComment(body, email, name);
}
}
Add a form and create a submit event in the template
<!-- comment-add.component.html -->
<form (submit)="onSubmit(name.value, email.value, body.value)" style="padding: 20px;">
<input #name style="width: 100%; font-size: 1.4rem;" type="text" placeholder="name">
<input #email style="width: 100%; font-size: 1.4rem;" type="text" placeholder="email">
<textarea #body style="width: 100%; font-size: 1.4rem;" placeholder="content"></textarea>
<button>Submit</button>
</form>
3. DELETE
In the template, add a delete button with a click event. Pass the id as a parameter
<!-- comment.component.html -->
<a routerLink="/comment-add">Add</a>
<div class="container">
<div class="card"
style="display: flex; flex-direction: column; justify-content: space-around; height: 150px; width: 600px; font-family: Arial, Helvetica, sans-serif; padding: 10px; background-color: antiquewhite; margin: 10px auto;"
*ngFor="let i of comments">
<p>{{i.id}}</p>
<p>{{i.body}}</p>
<div>
<p>{{i.name}}</p>
<p>{{i.email}}</p>
</div>
<button (click)="onDelete(i.id)">Delete</button>
</div>
</div>
Add a function with delete request in the service file
// comment.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Comment } from '../models/comment';
@Injectable({
providedIn: 'root',
})
export class CommentService {
URL = 'https://jsonplaceholder.typicode.com/comments/';
constructor(private http: HttpClient) {}
getComments(): Observable<Comment[]> {
return this.http.get<Comment[]>(this.URL);
}
addComment(body: string, name: string, email: string) {
const comment: Comment = {
body: body,
email: email,
name: name,
};
this.http.post(this.URL, comment).subscribe(result => {
console.log(result)
});
}
deleteComment(id:string) {
this.http.delete(this.URL + id).subscribe(result => {
console.log(result)
})
}
}
// comment.component.ts
import { Component, OnInit } from '@angular/core';
import { Comment } from 'src/app/models/comment';
import { CommentService } from 'src/app/services/comment.service';
@Component({
selector: 'app-comment',
templateUrl: './comment.component.html',
styleUrls: ['./comment.component.css'],
})
export class CommentComponent implements OnInit {
comments: Comment[] = [];
constructor(private commentService: CommentService) {}
ngOnInit(): void {
this.commentService.getComments().subscribe((comments) => {
this.comments = comments;
});
}
onDelete(id: string | undefined) {
this.commentService.deleteComment(id as string);
}
}
<!-- comment.component.html -->
<a routerLink="/comment-add">Add</a>
<div class="container">
<div class="card"
style="display: flex; flex-direction: column; justify-content: space-around; height: 150px; width: 600px; font-family: Arial, Helvetica, sans-serif; padding: 10px; background-color: antiquewhite; margin: 10px auto;"
*ngFor="let i of comments">
<p>{{i.id}}</p>
<p>{{i.body}}</p>
<div>
<p>{{i.name}}</p>
<p>{{i.email}}</p>
</div>
<button (click)="onDelete(i.id)">Delete</button>
<button>Edit</button>
</div>
</div>
4. PUT
There are two ways of updating an item: PUT and FETCH. The difference between them is that FETCH only updates what is requested while PUT updates the entire value
In the template, add a delete button with a click event. Pass the id as a parameter
<!-- comment.component.html -->
<a routerLink="/comment-add">Add</a>
<div class="container">
<div class="card"
style="display: flex; flex-direction: column; justify-content: space-around; height: 150px; width: 600px; font-family: Arial, Helvetica, sans-serif; padding: 10px; background-color: antiquewhite; margin: 10px auto;"
*ngFor="let i of comments">
<p>{{i.id}}</p>
<p>{{i.body}}</p>
<div>
<p>{{i.name}}</p>
<p>{{i.email}}</p>
</div>
<button (click)="onDelete(i.id)">Delete</button>
<button>
<a [routerLink]="['/comment-edit', i.id]">
Edit
</a>
</button>
</div>
</div>
Add editComment function in the service file. To show what is selected, let's also add a GET request that will get one item
// comment.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Comment } from '../models/comment';
@Injectable({
providedIn: 'root',
})
export class CommentService {
URL = 'https://jsonplaceholder.typicode.com/comments/';
constructor(private http: HttpClient) {}
getComments(): Observable<Comment[]> {
return this.http.get<Comment[]>(this.URL);
}
addComment(body: string, name: string, email: string) {
const comment: Comment = {
body: body,
email: email,
name: name,
};
this.http.post(this.URL, comment).subscribe(result => {
console.log(result)
});
}
deleteComment(id:string) {
this.http.delete(this.URL + id).subscribe(result => {
console.log(result)
})
}
getComment(id:string):Observable<Comment> {
return this.http.get<Comment>(this.URL + id)
}
editComment(id:string, body: string, name: string, email: string) {
const comment: Comment = {
body: body,
email: email,
name: name,
};
this.http.put(this.URL + id, comment).subscribe(result => {
console.log(result)
})
}
}
Use ActivatedRoute in the component-edit class to catch the id of the selected item to update
// component-edit.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Comment } from 'src/app/models/comment';
import { CommentService } from 'src/app/services/comment.service';
@Component({
selector: 'app-comment-edit',
templateUrl: './comment-edit.component.html',
styleUrls: ['./comment-edit.component.css'],
})
export class CommentEditComponent implements OnInit {
id!: string;
comment!: Comment;
constructor(
private commentService: CommentService,
private activatedRoute: ActivatedRoute
) {}
ngOnInit(): void {
this.id = this.activatedRoute.snapshot.params['id'];
this.commentService.getComment(this.id).subscribe((comment) => {
this.comment = {
name: comment.name,
body: comment.body,
email: comment.email,
};
});
}
onSubmit(name: string, email: string, body: string) {
this.commentService.editComment(this.id, body, email, name);
}
}
Bind the form value to the value of the field using attribute binding in the edit template file
<!-- comment-add.component.html -->
<form (submit)="onSubmit(name.value, email.value, body.value)" style="padding: 20px;">
<input #name style="width: 100%; font-size: 1.4rem;" type="text" placeholder="name" [value]="comment.name">
<input #email style="width: 100%; font-size: 1.4rem;" type="text" placeholder="email" [value]="comment.email">
<textarea #body style="width: 100%; font-size: 1.4rem;" placeholder="content" [value]="comment.body"></textarea>
<button>Submit</button>
</form>
Then the values will be populated
Try to update and you will see updated value in the network tap
We have seen Angular HttpClient in this writing
Enhancing the Form (Template Driven Form)
Angular Forms - Template-driven form
Angular template-driven form provides easier way to handle form manipulations. In this writing, we will see how to use the template-driven form. Implementation First, add the forms module in the module file //scr/app/app.module.ts import { NgModule } from
jin-co.tistory.com
Source Code
https://github.com/jin-co/web-mobile/tree/master/Angular/cheat-sheet/http
GitHub - jin-co/web-mobile
Contribute to jin-co/web-mobile development by creating an account on GitHub.
github.com
References
Traversy Media
Traversy Media features the best online web development and programming tutorials for all of the latest web technologies from the building blocks of HTML, CSS & JavaScript to frontend frameworks like React and Vue to backend technologies like Node.js, Pyth
www.youtube.com
'Frontend > Angular' 카테고리의 다른 글
Angular Library - Angular PWA (1) | 2023.03.30 |
---|---|
Angular Library - Angular Animations (1) | 2023.03.30 |
Angular Library - Angular Forms (0) | 2023.03.30 |
Angular Library - Angular Router (0) | 2023.03.30 |
Angular Library (1) | 2023.03.30 |