Angular 11 HttpClient + SpringBoot POST, PUT, DELETE

How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular 11

With previous posts, we had done 2 important things: fetching data from remote server by Angular HttpClient, and navigate among views by Angular Routing.

In this tutorial, we’ll go to next step – work with Rest APIs: How to use Angular HttpClient to POST, PUT & DELETE data on SpringBoot RestAPI Services.

Related Articles:
How to work with Angular Routing – Spring Boot + Angular 11
How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular 11
Angular 11 + Spring JPA + PostgreSQL example | Angular 11 Http Client – Spring Boot RestApi Server
Angular 11 + Spring JPA + MySQL example | Angular 11 Http Client – Spring Boot RestApi Server


I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: RELEASE
– Angular 11

II. Overview

For POST, PUT, DELETE data, We use Angular HTTP Client methods:

– post(url: string, body: any, options?: RequestOptionsArgs): Observable
– put(url: string, body: any, options?: RequestOptionsArgs): Observable
– delete(url: string, options?: RequestOptionsArgs): Observable

Detail implementation:


create(customer: Customer): Promise {
  ...
  return this.http.post(this.customersUrl, JSON.stringify(customer), {headers: this.headers})
  ...
}

update(customer: Customer): Promise {
  ...
  return this.http.put(url, JSON.stringify(customer), {headers: this.headers})
  ...
}

delete(id: number): Promise {
  ...
  return this.http.delete(url, {headers: this.headers})
  ...
}

angular-http-service-architecture

On SpringBoot Server side, we had 3 RequestMappings: @PostMapping, @PutMapping, @DeleteMapping


...

@PostMapping(value="/customer")
public Customer postCustomer(@RequestBody Customer customer){
    ...
}

@PutMapping(value="/customer/{id}")
public void putCustomer(@RequestBody Customer customer, @PathVariable int id){
	...
}

@DeleteMapping(value="/customer/{id}")
public void deleteCustomer(@PathVariable int id){
	...
}

...

About Angular Client‘ views, We design a new Add Customer Form and modify Customer Detail‘s view in the previous post as below:

angular http client post put deletet - add customer form

angular http client post put deletet - edit customer form

III. Practice

In the tutorial, we will re-use the sourcecode that we had done with the previous post. So you should check out it for more details:
How to work with Angular Routing – Spring Boot + Angular 11

Step to do:

With Angular Client:
– Implement new CreateCustomerComponent
– Re-Implement CustomerDetailComponent
– Re-Implement App Routing Module
– Re-Implement AppComponent
– Add new functions for DataService: CREATE – UPDATE – DELETE

With SpringBoot Service:
– Implement new Rest APIs: POST – UPDATE – DELETE

Deployment:
– Integrate Angular App and SpringBoot Server
– Run & Check results.

1. Implement new CreateCustomerComponent

Create new CreateCustomerComponent, see the new project’s structure:

angular http client post put deletet - new project structure

CreateCustomerComponent has 3 main functions:
onSubmit() & goBack() map with 2 buttons Submit & Back

angular http client post put deletet - back - submit button

newCustomer() maps with button Add to continuously create a new customer:

angular http client post put deletet - add new customer

Detail Sourcecode:


import { Customer } from '../customer';
import { DataService } from '../data.service';
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';

@Component({
  selector: 'app-create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
})
export class CreateCustomerComponent implements OnInit {
  customer = new Customer;
  submitted = false;
  constructor(private dataService: DataService,
              private location: Location) { }

  ngOnInit() {
  }

  newCustomer(): void {
    this.submitted = false;
    this.customer = new Customer();
  }

 private save(): void {
   this.dataService.create(this.customer);
 }

 onSubmit() {
   this.submitted = true;
   this.save();
 }

  goBack(): void {
    this.location.back();
  }
}

About CreateCustomerComponent‘s view, We use submitted variable to control the hidden parts:

<h3>Create Customer Form</h3>
<div [hidden]="submitted">
    <form (ngSubmit)="onSubmit()">
      <div class="form-group">
        <label for="firstname">First Name</label>
        <input type="text" class="form-control" id="firstname" required
        [(ngModel)]="customer.firstname" name="firstname">
      </div>
      
      <div class="form-group">
        <label for="lastname">Last Name</label>
        <input type="text" class="form-control" id="lastname" required
        [(ngModel)]="customer.lastname" name="lastname">
      </div>
      
      <div class="form-group">
        <label for="age">Age</label>
        <input type="number" class="form-control" id="age" required
        [(ngModel)]="customer.age" name="age">
      </div>
      
      <div class="btn-group" >
      	<button class="btn btn-primary" (click)="goBack()">Back</button>
      	<button type="submit" class="btn btn-success">Submit</button>
      </div>
    </form>
</div>

<div [hidden]="!submitted">
	<div class="btn-group ">
    	<h4>You submitted successfully!</h4>
    	<button class="btn btn-primary" (click)="goBack()">Back</button>
    	<button class="btn btn-success" (click)="newCustomer()">Add</button>
    </div>
</div>

[(ngModel)] is used for binding data customer: Customer between views and controllers of Angular Application.

2. Re-Implement CustomerDetailComponent

For CustomerDetailComponent, We add 2 new functions: onSubmit() and delete() for handling 2 buttons: Update and Delete

Details Sourcecode:


import { Component, OnInit, Input } from '@angular/core';

import { Customer } from '../customer';
import { DataService } from '../data.service';

import { ActivatedRoute, Params } from '@angular/router';

import { Location } from '@angular/common';

import 'rxjs/add/operator/switchMap';

@Component({
  selector: 'app-customer-detail',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css'],
})

export class CustomerDetailsComponent implements OnInit {

  customer = new Customer() ;
  submitted = false;

  constructor(
    private dataService: DataService,
    private route: ActivatedRoute,
    private location: Location
  ) {}

  ngOnInit(): void {
    this.route.params
      .switchMap((params: Params) => this.dataService.getCustomer(+params['id']))
      .subscribe(customer => this.customer = customer);
  }

  onSubmit(): void {
    this.submitted = true;
    this.dataService.update(this.customer);
  }

  delete(): void {
    this.dataService.delete(this.customer.id).then(() => this.goBack());
  }

  goBack(): void {
    this.location.back();
  }
}

angular http client post put deletet - update - delete button

About CustomerDetailComponent‘s view, We use form tag to handle Customer’s form submittion and
use submitted variable to control the hidden parts:

<h2>Edit Customer Form</h2>
<div [hidden]="submitted">
    <form (ngSubmit)="onSubmit()">
      <div class="form-group">
        <label for="firstname">First Name</label>
        <input type="text" class="form-control" id="firstname" required
        [(ngModel)]="customer.firstname" name="firstname">
      </div>
      
      <div class="form-group">
        <label for="lastname">Last Name</label>
        <input type="text" class="form-control" id="lastname" required
        [(ngModel)]="customer.lastname" name="lastname">
      </div>
      
      <div class="form-group">
        <label for="age">Age</label>
        <input type="number" class="form-control" id="age" required
        [(ngModel)]="customer.age" name="age">
      </div>
      
      <div class="btn-group">
		<button class="btn btn-primary" (click)="goBack()">Back</button>
    	<button type="submit" class="btn btn-success">Update</button>
		<button class="btn btn-danger" (click)="delete()">Delete</button>
	  </div>
      
    </form>
</div>

<div [hidden]="!submitted">
    <h4>Update successfully!</h4>
    <div class="btn-group">
      <button class="btn btn-primary" (click)="goBack()">Back</button>
      <button class="btn btn-success" (click)="submitted=false">Edit</button>
    </div>
</div>

3. Re-Implement App Routing Module

Add new path add for CreateCustomerComponent:


...

const routes: Routes = [
   { path: '', redirectTo: 'customer', pathMatch: 'full' },
   { path: 'customer',  component: CustomersComponent },
   { path: 'add', component: CreateCustomerComponent },
   { path: 'detail/:id', component: CustomerDetailsComponent }
];

...

4. Re-Implement AppComponent

Modify AppComponent‘s view:

<h2 style="color: blue">JSA - Angular Application!</h2>
<nav>
	<a routerLink="customer" class="btn btn-primary active" role="button" routerLinkActive="active">Customers</a> 
	<a routerLink="add" class="btn btn-primary active" role="button" routerLinkActive="active">Add</a>
</nav>
<router-outlet></router-outlet>

5. Add new functions for DataService: CREATE – UPDATE – DELETE

For CREATE, MODIFY, DELETE customers, in DataService, we implement 3 functions:
– create(customer: Customer): Promise
– update(customer: Customer): Promise
– delete(id: number): Promise

3 Angular HTTPClient‘s functions are used for implementation:

– post(url: string, body: any, options?: RequestOptionsArgs): Observable;
– put(url: string, body: any, options?: RequestOptionsArgs): Observable;
– delete(url: string, options?: RequestOptionsArgs): Observable;

Details sourcecode:


...

@Injectable()
export class DataService {
  
  private customersUrl = 'api/customer';  // URL to web API
  private headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) { }

  ...

  create(customer: Customer): Promise {
    return this.http
      .post(this.customersUrl, JSON.stringify(customer), {headers: this.headers})
      .toPromise()
      .then(res => res.json() as Customer)
      .catch(this.handleError);
  }

  update(customer: Customer): Promise {
    const url = `${this.customersUrl}/${customer.id}`;
    return this.http
      .put(url, JSON.stringify(customer), {headers: this.headers})
      .toPromise()
      .then(() => customer)
      .catch(this.handleError);
  }

  delete(id: number): Promise {
    const url = `${this.customersUrl}/${id}`;
    return this.http.delete(url, {headers: this.headers})
      .toPromise()
      .then(() => null)
      .catch(this.handleError);
  }
   
  ...
}

6. Implement new Rest APIs: POST – UPDATE – DELETE

Implement 3 Rest APIs:


...

@PostMapping(value="/customer")
public Customer postCustomer(@RequestBody Customer customer){
	int id = customers.size() + 1;
	customer.setId(id);
	customers.put(id, customer);
	return customer;
}

@PutMapping(value="/customer/{id}")
public void putCustomer(@RequestBody Customer customer, @PathVariable int id){
	customers.replace(id, customer);
}

@DeleteMapping(value="/customer/{id}")
public void deleteCustomer(@PathVariable int id){
	customers.remove(id);
}

...

>>> Related article: Spring Framework 4.3 New Feature RequestMapping: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

7. Integrate Angular App and SpringBoot Server

Angular4Client and SpringBoot server work independently on ports 8080 and 4200.
Goal of below integration: the client at 4200 will proxy any /api requests to the server.

Step to do:


{
    "/api": {
        "target": "http://localhost:8080",
        "secure": false
    }
}

– Edit package.json file for “start” script:


...
"scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
},
...

If you want to deploy Angular Application on SpringBoot‘s jar file, you can do following:

– Build the angular4client with command ng build --env=prod
– In pom.xml, use Maven plugin to copy all files from dist folder to /src/main/resources/static folder of SpringBoot server project.

<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
      <execution>
          <id>copy-resources</id>
          <phase>validate</phase>
          <goals><goal>copy-resources</goal></goals>
          <configuration>
              <outputDirectory>${basedir}/target/classes/static/</outputDirectory >
              <resources>
                  <resource>
                      <directory>${basedir}/../angular4client/dist</directory >
                  </resource>
              </resources>
          </configuration>
      </execution>
</executions>
</plugin>

>>> Related article: How to integrate Angular 11 with SpringBoot Web App and SpringToolSuite

8. Run & Check results

Build and Run the SpringBoot project with commandlines: mvn clean install and mvn spring-boot:run
Run the Angular App with command: npm start
Make a request: http://localhost:4200/, results:

–> Response’s data

response data - customer list

-> Customer List:

angular http client post put deletet - customer list

Press Add button. Then input new customer’s info:

add new customer

Press Submit button,

customer post - request data

customer post successfully

Press Back button,

result after add John

Then click to select John, edit firstname from ‘John’ to ‘Richard’. Press Update, then press Back button,

richard update data

edit customer

Now click to select Peter, the Application will navigate to Peter details view:

peter details

Press Delete button,

delete peter data

customer list after delete peter

IV. Sourcecode

AngularClientPostPutDelete
SpringBootAngularIntegration

2 thoughts on “Angular 11 HttpClient + SpringBoot POST, PUT, DELETE”

  1. I haven’t checked in here for a while because I thought it was getting boring, but the last few posts are great quality so I guess I will add you back to my everyday bloglist. You deserve it my friend 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *