본문 바로가기

Frontend/Angular

Angular Library - Angular HttpClient

반응형

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

Without a type
With 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 - YouTube

 

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

 

 

728x90
반응형

'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