Spring Boot Mongodb Angular Crud Example Github

Spring Boot MongoDb crud angular example git

Tutorial: “Spring Boot Mongodb Angular Crud Example Github – using Spring Boot Data & Atlas MongoDB”

In the tutorial, I introduce how to build an “Angular SpringBoot MongoDB CRUD Example RestAPIs” project with the help of SpringData and Atlas MongoDB for POST/GET/PUT/DELETE requests with step by step coding examples:

– SpringBoot project produces CRUD RestAPIs with MongoDB database documents using the supporting of Spring Data.
– Angular project will consume the SpringBoot CRUD RestAPIs then show up on component’s views.

Related posts:


– I draw a fullstack overview Diagram Architecture from Angular Frontend to MongoDB database through SpringBoot RestAPI backend.
– Develop SpringBoot CRUD RestAPIs with the supporting of SpringWeb Framework.
– Implement Angular CRUD application with the Angular Httpclient to do CRUD request (Post/Get/Put/Delete) to SpringBoot Backend APIs.
– I create a testsuite with a number of integrative testcases with CRUD RestAPI requests from Angular HttpClient to do CRUD requests to SpringBoot RestAPIs Server and save/retrieve data to MongoDB database.

Overall Architecture System: Spring Boot Mongodb Angular Crud Example Github

Angular SpringBoot MongoDB Diagram Architecture
Angular SpringBoot MongoDB Diagram Architecture
  • We build a backend: SpringBoot CRUD Application with MongoDB Atlas that provides RestAPIs for POST/GET/PUT/DELETE data entities and store them in MongoDB database.
  • We implement Angular CRUD Application that use Angular HTTPClient to interact (call/receive requests) with SpringBoot CRUD application and display corresponding data in Angular Component.

Overview Spring Boot Mongodb Angular Crud Example Github Design Application

SpringBoot MongoDB CRUD RestAPI Fullstack Diagram Architecture
SpringBoot MongoDB CRUD RestAPI Fullstack Diagram Architecture

I build a SpringBoot project that handle all Post/Get/Put/Delete requests from RestClient and do CRUD operations to MongoDB Atlas database to save/retrieve/update and delete documents from MongoDB and returns back to Restclient the corresponding messages.

In the tutorial “Spring Boot Mongodb Angular Crud Example”, We build a SpringBoot project with 3 layers:
– MongoDB Repository is used to interact with MongoDB database by a set of CRUD operations.
– Service is the middle-ware layer for interating with RestController layer and MongoDB Repository layer. This is a transforming machine, it gets the needed data from web-requests through RestController and do CRUD operation to MongoDB via MongoDB Repository layer.
– RestController layer is a web layer for SpringBoot project, it will directly handle all incomming requests and do the corressponding responses to the calling client.

Angular HttpClient CRUD Application Design

Angular CRUD RestAPI Application Frontend Architecture Diagram
Angular CRUD RestAPI Application Frontend Architecture Diagram

In the tutorial “Spring Boot Mongodb Angular Crud Example Github”, Angular CRUD Application is designed with 3 main layers:

  • Service Layer is used to define Angular Common Services and Angular HttpClient Services to do CRUD requests with Nodejs RestAPIs
  • Component Layer is used to define Angular Components to display views in Browser.
  • Router Layer is used to define all Angular navigation URLs mapping with the corresponding Angular Components
Angular CRUD RestAPIs Project Structure
Angular CRUD RestAPIs Project Structure

Angular CRUD Application defines 3 components, 2 services, 1 routers, and 2 data models:

– Angular Components:

  • add-customer component is used to post a new data to MongoDB via Nodejs RestAPI
  • list-customer component is used to display all data on views, delete a data and update a data with
    a given id to MongoDB using Nodejs RestAPIs: Get/Put/Delete
  • message component is used to define a view to show logging message on browser

– Angular Services:

  • customer.service.ts defines CRUD Angular httpclient post/get/put/delete requests to Node.js Express RestAPIs
  • message.service.ts defines an array storage to log all messages when the Angular CRUD App running

– Angular Router: app-routing.module.ts defines how to map a corresponding Angular component with an URL.

– Models:

  • customer.ts defines the main data model of Angular application.
  • message.ts defines the response data model between Nodejs and Angular application.

Spring Boot Mongodb Angular Crud Example Github – Project Goal

– Angular adds a data:

Angular Post request to MongoDB via SpringBoot RestAPIs
Angular Post request to MongoDB via SpringBoot RestAPIs

– Angular SpringBoot MongoDB list all data:

Angular retrieve all documents from MongoDB via SpringBoot RestAPI
Angular retrieve all documents from MongoDB via SpringBoot RestAPI

– Angular update a data:

Angular update a document to MongoDB via SpringBoot RestAPI
Angular update a document to MongoDB via SpringBoot RestAPI

– Delete a record:

Angular delete a MongoDB document via SpringBoot RestAPI
Angular delete a MongoDB document via SpringBoot RestAPI

– Check all MongoDB’s documents:

Check MongoDB documents after doing all CRUD requests via SpringBoot restapi
Check MongoDB documents after doing all CRUD requests via SpringBoot restapi

Spring Boot Mongodb Angular Crud Example Github – Backend Development

Now it’s time for building the “SpringBoot MongoDB CRUD RestAPIs Example” project with a set of simple steps:

  • Create SpringBoot project
  • Configure MongoDB Database
  • Define Spring Data MongoDB’s Document Model
  • Define SpringBoot MongoDB Repository
  • Implement SpringBoot Customer Service
  • Implement SpringBoot MongoDB CRUD RestAPIs

Let’s go!

Create SpringBoot MongoDB project

In the tutorial “Spring Boot Mongodb Angular Crud Example Github”, We use SpringToolSuite to create a simple SpringBoot project with below structure:

SpringBoot MongoDB CRUD RestAPIs project structure
SpringBoot MongoDB CRUD RestAPIs project structure
  • application.properties is used to add the SpringBoot application’s configurations such as: database configuration (MongoDB, MySQL, PostgreSQL), threadpool, Hibernate, JPA …
  • repository package is used to define a SpringBoot MongoDB repository to do CRUD operations with MongoDB
  • rest package is used to implement a SpringBoot RestAPI controller to handle all incomming requests (post/get/put/delete) and response to rest-client.
  • service package is used to implement a middleware machine between RestAPIs controller and Mongo Repository of SpringBoot project.
  • model package is used to define the MongoDB document’s schema that maps with the document format in MongoDB database

For handling the web-request and doing CRUD operations with MongoDB database, we need the supporting of 2 SpringBoot dependencies: spring-boot-starter-web and spring-boot-starter-data-mongodb. So adding it to pom.xml file:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Application Properties Spring Boot Mongodb Example

To initialize a connection with MongoDB Atlas, we open the file application.properties and add below uri configure:

#mongodb
spring.data.mongodb.uri=mongodb+srv://loizenjava:loizenjava@cluster0.gmd7e.mongodb.net/loizenjavadb?retryWrites=true&w=majority

Define Spring Data MongoDB’s Document Model

Now we define a Customer class for mapping data between SpringBoot application with MongoDB documents:

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection = "customers")
public class Customer {
	@Id
	private String id;
	private String firstname;
	private String lastname;
	private Integer age;
	private String address;
	
	@Field
	private String copyrightby = "https://loizenjava.com";

	public Customer(String firstname, String lastname, int age, String address) {
		this.firstname = firstname;
		this.lastname = lastname;
		this.age = age;
		this.address = address;
	}
        // getters and setters 
        // ...

@Document is used to identify a domain object to be persisted to MongoDB.

Here is a sample domain object to be persisted to MongoDB:

MongoDB Document schema
MongoDB Document schema

Define SpringBoot MongoDB Repository

– Create a CustomerRepository interface that extends MongoRepository:

package com.loizenjava.springboot.mongodb.repository;

import org.springframework.data.mongodb.repository.MongoRepository;

import com.loizenjava.springboot.mongodb.model.Customer;

public interface CustomerRepository extends MongoRepository<Customer, String>{
}

With the CustomerRepository interface, we can do all CRUD operations (save/retrieve/update/delete) from SpringBoot application to MongoDB database.

Implement SpringBoot RestAPI Customer Service

Now we implement a middle service between RestController layer and MongoDB Repository, by creating a file CustomerService that uses mongodb repository CustomerRepository as below code:


package com.loizenjava.springboot.mongodb.service;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.loizenjava.springboot.mongodb.exception.CustomException;
import com.loizenjava.springboot.mongodb.model.Customer;
import com.loizenjava.springboot.mongodb.repository.CustomerRepository;

@Service
public class CustomerService {
	
	@Autowired
	CustomerRepository repo;
	
	public Customer saveCustomer(Customer customer){
		return repo.save(customer);
	}
	
	public List<Customer> retrieveAllCustomers(){
		return repo.findAll();
	}
	
	public Customer updateCustomer(String id, Customer customer) throws CustomException {
		
		Optional<Customer> customerOpt = repo.findById(id);
		
		if(!customerOpt.isPresent()) {
			throw new CustomException("404", "Can not find a customer for updating with id = " + id);
		}
			
		Customer _customer = customerOpt.get();
		
		_customer.setFirstname(customer.getFirstname());
		_customer.setLastname(customer.getLastname());
		_customer.setAddress(customer.getAddress());
		_customer.setAge(customer.getAge());
		
		repo.save(_customer);
		
		return _customer;
	}
	
	public void deleteCustomerById(String id) {
		repo.deleteById(id);
	}
}

Implement SpringBoot MongoDB CRUD RestAPIs

Related post: SpringBoot RestAPIs @GetMapping, @PostMapping, @DeleteMapping, @PutMapping, @PatchMapping

We use SpringWeb to implement 4 RestAPIs for Post/Get/Put/Delete requests as below list:

  • SpringBoot Post request – we define a Post RestApi: /api/customers/create is used to save a single Customer data to MongoDB database.
  • SpringBoot Get request – we define a GET RestApi: /api/customers/retrieveinfos is used to retrieve all Customer documents from MongoDB database.
  • SpringBoot Put request – we define a restapi /api/customers/updatebyid/{id} to update a Customer document from MongoDB via a given id and request body’s data
  • SpringBoot Delete request – we define a Delete RestApi: /api/customers/deletebyid/{id} is used to delete a Customer document from MongoDB via a give id
package com.loizenjava.springboot.mongodb.rest;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.loizenjava.springboot.mongodb.exception.CustomException;
import com.loizenjava.springboot.mongodb.message.ResponseMsg;
import com.loizenjava.springboot.mongodb.model.Customer;
import com.loizenjava.springboot.mongodb.service.CustomerService;

@RestController
@RequestMapping("/api/customers")
@CrossOrigin(origins = { "http://localhost:4200"})
public class WebController {
	
	@Autowired
	CustomerService customerService;

	@PostMapping("/create")
	public ResponseEntity<ResponseMsg> saveCustomer(@RequestBody Customer customer, HttpServletRequest request) {
		try {
			// save to MongoDB database
			Customer _customer = customerService.saveCustomer(customer);
			
			String message = "Upload Successfully a Customer to MongoDB with id = " + _customer.getId();
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, request.getRequestURI(), 
											List.of(customer)), HttpStatus.OK);	
		}catch(Exception e) {
			String message = "Can NOT upload  a Customer to MongoDB database";
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, request.getRequestURI(), 
											e.getMessage()), HttpStatus.OK);
		}
	}
	
	@GetMapping("/retrieveinfos")
	public ResponseEntity<ResponseMsg> getAllCustomers(HttpServletRequest request) {
		try {
			// get all documents from MongoDB database
			List<Customer> customers = customerService.retrieveAllCustomers();
			
			String message = "Retrieve all Customer successfully!";
			
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, 
									request.getRequestURI(), customers), HttpStatus.OK);	
		}catch(Exception e) {
			String message = "Can NOT retrieve all data from MongoDB database";
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, request.getRequestURI(), 
									e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@PutMapping("/updatebyid/{id}")
	public ResponseEntity<ResponseMsg> updateCustomer(@PathVariable String id, @RequestBody Customer customer,
															HttpServletRequest request) {
		try {
			// update a customer to MongoDB
			Customer _customer = customerService.updateCustomer(id, customer);
			String message = "Successfully Update a Customer to MongoDB with id = " + id;
			
			return new ResponseEntity<ResponseMsg> (new ResponseMsg(message, request.getRequestURI(), 
														List.of(_customer)), HttpStatus.OK);
		} catch (CustomException ce) {
			String message = "Can NOT update to MongoDB a Customer with id = " + id;
			return new ResponseEntity<ResponseMsg> (new ResponseMsg(message, request.getRequestURI(), 
					ce.getMessage()), HttpStatus.NOT_FOUND);
		} catch (Exception e) {
			String message = "Can NOT update to MongoDB a Customer with id = " + id;
			return new ResponseEntity<ResponseMsg> (new ResponseMsg(message, request.getRequestURI(), 
					e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
	
	@DeleteMapping("/deletebyid/{id}")
	public ResponseEntity<ResponseMsg> deleteCustomerById(@PathVariable String id, HttpServletRequest request) {
		try {
			// delete a Customer from MongoDB database using ID
			customerService.deleteCustomerById(id);
			
			String message = "Successfully delete a Customer from MongoDB database with id = " + id;
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, request.getRequestURI()), HttpStatus.OK);
		} catch(Exception e) {
			String message = "Can Not delete a Customer from MongoDB database with id = " + id;
			return new ResponseEntity<ResponseMsg>(new ResponseMsg(message, request.getRequestURI(), e.getMessage()), 
														HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
}

Integrative Testing – Spring Boot Mongodb Angular Crud Example Github

1. Testcase 1 – Post request – Save a single object to MongoDB

SpringBoot Post data to MongoDB
SpringBoot Post data to MongoDB

– Check MongoDB document after Posting data:

Check MongoDB database documents
Check MongoDB database documents

2. Testcase 2 – Get request – retrieve all documents from MongoDB

SpringBoot retrieves all documents from MongoDB database
SpringBoot retrieves all documents from MongoDB database

3. Testcase 3 – Put request – SpringBoot RestAPI updates data to MongoDB

SpringBoot RestAPI updates document to MongoDB
SpringBoot RestAPI updates document to MongoDB

– Check MongoDB document after updating:

Check MongoDB's document is updated
Check MongoDB’s document is updated

4. Testcase 4 – Delete request – SpringBoot RestAPI delete a single document from MongoDB

SpringBoot Delete RestAPIs successfully
SpringBoot Delete RestAPIs successfully

Angular CRUD Application Overview with SpringBoot RestAPIs

Angular CRUD RestAPI Application Frontend Architecture Diagram
Angular CRUD RestAPI Application Frontend Architecture Diagram

– For more details, we go back to the session: Angular CRUD Design

Create Angular Application

We create Angular CRUD project by commandline: ng new AngularHttpclient.
– Create 3 components AddCustomer, ListCustomers, Message by cmd:


ng g component AddCustomer
ng g component ListCustomers
ng g component Message

– Create 2 Angular services CustomerService, MessageService by cmd:


ng g service customer
ng g service message

– Create 2 models Customer and Message by cmd:


ng g class customer;
ng g class message;

Create Angular Typescript Model

We define Customer class with 5 attributes:

export class Customer {
    id: number;
    firstname: string;
    lastname: string;
    age: number;
    address: string
}

Create Typescript Message

We define Message class as below:

import { Customer } from './customer';

export class Message {
    message: string;
    error: string;
    customers: Customer[];
}

Implement Angular CRUD HttpClient Service

For interacting with Backend RestAPIs, we use Angular built-in Httpclient service:

@Injectable({
  providedIn: 'root'
})
export class CustomerService {

  private baseUrl = 'http://localhost:8080/api/customers';

  constructor(private http: HttpClient) { }
  
  ...

To handle Error, we implement a function private handleError(error: HttpErrorResponse):

private handleError(error: HttpErrorResponse) {
  if (error.error instanceof ErrorEvent) {
    // A client-side or network error occurred. Handle it accordingly.
    console.error('An error occurred:', error.error.message);
  } else {
    // The backend returned an unsuccessful response code.
    // The response body may contain clues as to what went wrong,
    console.error(
      `Backend returned code ${error.status}, ` +
      `body was: ${error.error}`);
  }
  // return an observable with a user-facing error message
  return throwError(
    'Something bad happened; please try again later.');
};

Angular HttpClient Post request

createCustomer(customer: Customer): Observable<Message> {
    return this.http.post<Message>(`${this.baseUrl}` + `/create`, customer)
                .pipe(
                  retry(3),
                  catchError(this.handleError)
                );
}

– The above function posts a Customer to SpringBoot backend server at URL http://localhost:8080/api/customers/create
retry(3) is used to retry a failed request up to 3 times

Angular HttpClient Get request

– Angular Client retrieve all data from PostgreSQL via Nodejs Express CRUD backend by a GET request at URL http://localhost:8080/api/customers/retrieveinfos.

retrieveAllCustomers(): Observable {
    return this.http.get(`${this.baseUrl}` + `/retrieveinfos`)
                  .pipe(
                    retry(3),
                    catchError(this.handleError)
                  );
}

Angular HttpClient Put request

– Angular client updates a data using Angular built-in Httpclient by a PUT request at URL:
http://localhost:8080/api/customers/updatebyid/{id}

updateCustomer(customer: Customer): Observable<Message> {
    return this.http.put<Message> (`${this.baseUrl}` + `/updatebyid/` + customer.id, customer)
      .pipe(
          retry(3),
          catchError(this.handleError)
        );
}

Angular HttpClient Delete request

– Angular client deletes a data from PostgreSQL by a given id using built-in Angular Httpclient by a Delete request at URL:
http://localhost:8080/api/customers/deletebyid/{id}:


deleteCustomer(id: number): Observable<Message> {
    return this.http.delete<Message>(`${this.baseUrl}` + `/deletebyid/` + id)
          .pipe(
            retry(3),
            catchError(this.handleError)  
          );
}

Implement Angular Message Service

For tracking the proccessing of each step of Angular CRUD Application, we implement a Message service to store tracing-logs message then display them on Html.

The message.service.ts has an string array messages to store tracing-log messages and 2 functions: add(message: string) and clear()

– Coding:


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MessageService {
  messages: string[] = [];

  add(message: string) {
    this.messages.push(message);
  }

  clear(){
    this.messages = [];
  }
}

Implement Angular Post Component: adding data

AddCustomerComponent is used to post a new data Customer to PostgreSQL via Nodejs CRUD Application server.
– We have 2 parts:

  • add-customer.component.ts file
  • add-cusomer.component.html file

1. add-customer.component.ts file

import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';
import { Message } from '../message';
import { MessageService } from '../message.service';

@Component({
  selector: 'app-add-customer',
  templateUrl: './add-customer.component.html'
})
export class AddCustomerComponent implements OnInit {
  customer: Customer;
  /**
   * Constructing Http Customer Service
   * @param customerService 
   */
  constructor(private customerService: CustomerService,
                private messageService: MessageService) { }

  ngOnInit(): void {
    this.customer = new Customer();
  }

  /**
   * Store a Customer to backend server
   */
  save() {
    this.customerService.createCustomer(this.customer)
          .subscribe((message: Message) => {
            console.log(message);
            let customer = message.customers[0];
            let msg = "Success -> Post a Customer: " 
                + "<ul>"
                    + "<li>id: " + customer.id + "</li>"  
                    + "<li>firstname: " + customer.firstname + "</li>"
                    + "<li>lastname: " + customer.lastname + "</li>"
                    + "<li>age: " + customer.age + "</li>"
                    + "<li>address: " + customer.address + "</li>"
                + "</ul>";

            this.messageService.add(msg);
          }, error => {
            console.log(error);
            let msg = "Error! -> Action Posting a Customer:" 
                      + "<ul>"
                        + "<li>id = " + this.customer.id + "</li>"  
                        + "<li>firstname = " + this.customer.firstname + "</li>"
                        + "<li>lastname = " + this.customer.lastname + "</li>"
                        + "<li>age = " + this.customer.age + "</li>"
                        + "<li>address = " + this.customer.address + "</li>"
                      + "</ul>";

            this.messageService.add(msg);
          });
  }

  reset(){
    this.customer = new Customer();
  }

  /**
   * Function handles form submitting
   */
  onSubmit() {
    this.save();
    this.reset();
  }
}

2. Implement add-customer.component.html view:

<h2>Create Customer</h2>
<div>
  <form (ngSubmit)="onSubmit()"> 
    <!-- First name -->   
    <div class="form-group">
      <label for="firstname">First Name:</label>
      <input type="text" class="form-control" placeholder="Enter Firstname" 
                id="firstname" required [(ngModel)]="customer.firstname" name="firstname">
    </div>
    <!-- Last name -->
    <div class="form-group">
        <label for="lastname">Last Name:</label>
        <input type="text" class="form-control" placeholder="Enter Lastname" 
                  id="lastname" required [(ngModel)]="customer.lastname" name="lastname">
    </div>  
    <!-- Address -->
    <div class="form-group">
        <label for="address">Address:</label>
        <input type="text" class="form-control" placeholder="Enter Address" 
                  id="address" required [(ngModel)]="customer.address" name="address">
    </div>        
    
    <!-- Age -->
    <div class="form-group">
      <label for="age">Age</label>
      <input type="number" class="form-control" placeholder="Enter Age" 
                  id="age" required [(ngModel)]="customer.age" name="age">
    </div>
 
    <button type="submit" class="btn btn-success">Submit</button>
  </form>
</div>
<app-message></app-message>

Implement Angular List Component: retrieve all data

ListCustomersComponent has 4 main functions:

  • Show all Customers
  • Show details a Customers
  • Delete a Customer
  • Update a Customer

1. Implement list-customers.component.ts:

import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { MessageService } from '../message.service';
import { CustomerService } from '../customer.service';
import { Message } from '../message';

@Component({
  selector: 'app-list-customers',
  templateUrl: './list-customers.component.html'
})
export class ListCustomersComponent implements OnInit {

  customers: Array<Customer> = [];
  showCustomer: Customer;
  isSelected: boolean = false;
  deletedCustomer: Customer;
  returnedMessage: string;

  constructor(private customerService: CustomerService,
                private messageService: MessageService) { }

  setCustomerDetails(customer: Customer){
    this.isSelected=!this.isSelected;
    if(this.isSelected){
      this.showCustomer = customer;
    }else{
      this.showCustomer = undefined;
    }
  }

  /**
   * Set deletedCustomer and reset returnedMessage = undefined
   * @param deleteCustomer
   */
  prepareDeleteCustomer(deleteCustomer: Customer){
    //assign delete-Customer
    this.deletedCustomer = deleteCustomer;
    // reset returned-Message
    this.returnedMessage = undefined;
  }

  /**
   * Delete a Customer by ID
   */
  deleteCustomer(){

    console.log("--- Access delelteCustomer() function");

    this.customerService.deleteCustomer(this.deletedCustomer.id)
                      .subscribe((message: Message) => {
                          console.log(message);
                          // remove a deletedCustomer from customers list on view
                          this.customers = this.customers.filter(customer => {
                            return customer.id != this.deletedCustomer.id;
                          })

                          // set a showing message in delete modal
                          this.returnedMessage = message.message;

                          // just reset showCustomer for not showing on view
                          this.showCustomer = undefined;

                          // add the delete message to message app for showing
                          this.messageService.add(message.message);
                        },
                        (error) => {
                          console.log(error);
                          let errMsg: string = "Error! Details: " + error;
                          this.messageService.add(errMsg);
                        });
  }

  /**
   * Update Customer function
   */
  updateCustomer() {
    this.customerService.updateCustomer(this.showCustomer)
                      .subscribe((message: Message) => {
                        console.log(message);
                        // update customers list
                        this.customers.map(x => {
                          if(x.id == this.showCustomer.id){
                            x = this.showCustomer;
                          }
                        });

                        let msg: string = "Update Successfully! -> New Customer's properties: <br>"
                                          + "<ul>"
                                            + "<li>" + "id: " + this.showCustomer.id + "</li>"
                                            + "<li>" + "firstname: " + this.showCustomer.firstname + "</li>"
                                            + "<li>" +  "lastname: " + this.showCustomer.lastname + "</li>"
                                            + "<li>" +  "age: " + this.showCustomer.age + "</li>"
                                            + "<li>" +  "address: " + this.showCustomer.address + "</li>"
                                          + "</ul>";
                        this.messageService.add(msg);
                      }
                      , (error) => {
                        console.log(error);
                        let errMsg = "Update Fail ! Error = " + error;
                        this.messageService.add(errMsg);
                      });
  }

  /**
   * Retrieve all Customer from Backend
   */
  retrieveAllCustomers() {
    this.customerService.retrieveAllCustomers()
                  .subscribe((message: Message) => {
                    console.log(message);
                    this.customers = message.customers;
                  }
                  , (error) => {
                    console.log(error);
                  });
  }

  ngOnInit(): void {
    this.retrieveAllCustomers();
  }
}

2. Implement list-customers.component.html:

<div *ngIf="customers.length">
    <h3>Customers</h3>
    <br>
    <table class="table table-hover table-sm">
        <thead class="thead-dark">
          <tr>
            <th>Id</th>
            <th>Firstname</th>
            <th>Address</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
            <tr *ngFor="let customer of customers">
              <td>
                <button type="button" class="btn btn-primary" (click)="setCustomerDetails(customer)">
                  {{customer.id}}
                </button>
              </td>
              <td>{{customer.firstname}}</td>
              <td>{{customer.address}}</td>
              <td>
                <button type="button" class="btn btn-danger" 
                  data-toggle="modal" data-target="#delete-modal" 
                                (click)=prepareDeleteCustomer(customer) >&times;</button>
              </td>
            </tr>
        </tbody>
    </table>
</div>

<!-- The Modal -->
<div class="modal fade" id="delete-modal">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
    
    <!-- Modal Header -->
    <div class="modal-header">
      <h4 class="modal-title">Delete!</h4>
      <button type="button" class="close" data-dismiss="modal">&times;</button>
    </div>
    
    <!-- Modal body -->
    <div class="modal-body">
        <div *ngIf="deletedCustomer">
          <p [hidden] = "returnedMessage">
            Do you want delete a customer with id = {{deletedCustomer.id}}
          </p>
          <p [hidden] = "!returnedMessage">
            {{returnedMessage}}
          </p>
        </div>
    </div>
    
    <!-- Modal footer -->
    <div class="modal-footer">
      <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
      <button [hidden] = "returnedMessage" type="button" class="btn btn-danger" (click)="deleteCustomer()">Delete</button>
    </div>				
    </div>
  </div>
  </div>

<div *ngIf="showCustomer">
    <h3>Update Customer</h3>
    <form (ngSubmit)="updateCustomer()"> 
        <!-- ID -->   
        <div class="form-group">
          <label for="id">Id:</label>
          <input type="numer" class="form-control"
                    id="id" required [(ngModel)]="showCustomer.id" name="id" disabled>
        </div>      
        <!-- First name -->   
        <div class="form-group">
          <label for="firstname">First Name:</label>
          <input type="text" class="form-control" placeholder="Enter Firstname" 
                    id="firstname" required [(ngModel)]="showCustomer.firstname" name="firstname">
        </div>
        <!-- Last name -->
        <div class="form-group">
            <label for="lastname">Last Name:</label>
            <input type="text" class="form-control" placeholder="Enter Lastname" 
                      id="lastname" required [(ngModel)]="showCustomer.lastname" name="lastname">
        </div>  
        <!-- Address -->
        <div class="form-group">
            <label for="address">Address:</label>
            <input type="text" class="form-control" placeholder="Enter Address" 
                      id="address" required [(ngModel)]="showCustomer.address" name="address">
        </div>        
        
        <!-- Age -->
        <div class="form-group">
          <label for="age">Age</label>
          <input type="number" class="form-control" placeholder="Enter Age" 
                      id="age" required [(ngModel)]="showCustomer.age" name="age">
        </div>
     
        <button type="submit" class="btn btn-success">Update</button>
      </form>
</div>
<app-message></app-message>


<script>
  let pathname = window.location.pathname;
  if(pathname == ""){
      $(".nav .nav-item a:first").addClass("active");
      $(".nav .nav-item a:last").removeClass("active");
  } else if (pathname == "/customers") {
      $(".nav .nav-item a:last").addClass("active");
      $(".nav .nav-item a:first").removeClass("active");
  }
  alert("ok");
</script>

Implement Angular Message Component

MessageComponent is used to show all tracing-log messages in html view.

1. Implement message.component.ts:

import { Component, OnInit } from '@angular/core';
import { MessageService } from '../message.service';

@Component({
  selector: 'app-message',
  templateUrl: './message.component.html'
})
export class MessageComponent {
  constructor(public messageService: MessageService) {}
}

2. Implement message.component.html:

<div *ngIf="messageService.messages.length">
    <h3>Messages</h3>
    <button type="button" class="btn btn-secondary" (click)="messageService.clear()">clear</button>
    <br>
    <ol>
      <li *ngFor='let message of messageService.messages'>
        <div [innerHTML]="message">
        </div>
      </li>
    </ol>
  </div>

Configure Angular Routing Module

To handle the navigation from one view to the next, you use the Angular router. The router enables navigation by interpreting a browser URL as an instruction to change the view.

The following command uses the Angular CLI to generate a basic Angular app with an app routing module, called AppRoutingModule, which is an NgModule where you can configure your routes.

ng new routing-app --routing

How to Define a route? -> There are three fundamental building blocks to creating a route.

1. Import the AppRoutingModule into AppModule and add it to the imports array.
The Angular CLI performs this step for you. However, if you are creating an app manually or working with an existing, non-CLI app, verify that the imports and configuration are correct.


import { AppRoutingModule } from './app-routing.module';
...

@NgModule({
  declarations: [
	...
  ],
  imports: [
	...
    AppRoutingModule,
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

2. Define your routes in your Routes array for “Angular Nodejs PostgreSQL CRUD Example”:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AddCustomerComponent } from './add-customer/add-customer.component';
import { ListCustomersComponent } from './list-customers/list-customers.component';

const routes: Routes = [
  { 
    path: '', 
    component: AddCustomerComponent 
  },
  { 
    path: 'customers', 
    component: ListCustomersComponent 
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

3. Add your routes to your application.
In the index.html file, we add below html code for navigating URL:


<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
  <ul class="navbar-nav">
    <li class="nav-item" id="li_add_customer">
      <a class="nav-link" href="">Add Customer</a>
    </li>
    <li class="nav-item" id="li_list_customers">
      <a class="nav-link" href="/customers">List Customers</a>
    </li>
  </ul>
</nav>

Next, update your component template to include . This element informs Angular to update the application view with the component for the selected route. So in main component,open app.component.ts file, add the tag:


<router-outlet></router-outlet>

Modify Angular Index.html View Page

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularHttpclient</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <!-- jQuery library -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <!-- Popper JS -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <!-- Latest compiled JavaScript -->
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
  <div class="container" >  
    <div class="col-sm-5" style="background-color: #ffffcc; margin:10px;padding:10px; border-radius: 5px">
      <nav class="navbar navbar-expand-sm bg-primary navbar-dark">
        <ul class="navbar-nav">
          <li class="nav-item" id="li_add_customer">
            <a class="nav-link" href="">Add Customer</a>
          </li>
          <li class="nav-item" id="li_list_customers">
            <a class="nav-link" href="/customers">List Customers</a>
          </li>
        </ul>
      </nav>
      <app-root></app-root>
    </div>
  </div>
  <script>
    $(document).ready(function() {
      (function(){
        let pathname = window.location.pathname;
        if(pathname == "/"){
            $("#li_add_customer").addClass("active");
            $("#li_list_customers").removeClass("active");
        } else if (pathname == "/customers") {
            $("#li_list_customers").addClass("active");
            $("#li_add_customer").removeClass("active");
        } 
      })();
    });
  </script>
</body>
</html>

Integrative Testing: Spring Boot Mongodb Angular Crud Example Github

Okay, now we do a set of testcases for the tutorial: “Spring Boot Mongodb Angular Crud Example Github using SpringData and Atlas MongoDB”.

1. Testcase 1: Angular Post data to MongoDB through SpringBoot RestAPI:

– Network Logging:

Testcase 1 – Angular post data to Mongodb Atlas
Testcase 1 – Angular post data to Mongodb Atlas

– Angular Post data:

Angular Post data to MongoDB via SpringBoot RestAPI
Angular Post data to MongoDB via SpringBoot RestAPI

– Angular Message Logs:

Angular Message Logs
Angular Message Logs

1. Testcase 2: Angular Get All data from MongoDB through SpringBoot RestAPI:

– Network Logging:

Testcase 2 - Retrieve all document from MongoDB via SpringBoot RestAPI
Testcase 2 – Retrieve all document from MongoDB via SpringBoot RestAPI

– Angular List documents:

Testcase 2 - Angular show all MongoDB documents in View
Testcase 2 – Angular show all MongoDB documents in View

3. Testcase 3: Angular Put data to MongoDB through SpringBoot RestAPI:

– Network Logging:

Testcase 3 - Angular update a document to MongoDB via SpringBoot RestAPI
Testcase 3 – Angular update a document to MongoDB via SpringBoot RestAPI

– Angular Update Successfully:

Angular update MongoDB document successfully
Angular update MongoDB document successfully

4. Testcase 4: Angular Delete data from MongoDB through SpringBoot RestAPI:

Testcase 4 - Angular delete a MongoDB document via SpringBoot RestAPI
Testcase 4 – Angular delete a MongoDB document via SpringBoot RestAPI

– Check MongoDB after doing CRUD requests:

Testcase 4 - Check mongodb documents after doing CRUD requests
Testcase 4 – Check mongodb documents after doing CRUD requests

Further Reading

Related posts:


Sourcecode – Spring Boot Mongodb Angular Crud Example Github

Below is clearly running sourcecode for the tutorial “Spring Boot Mongodb Angular Crud Example Github” with SpringData Mongo and Atlas MongoDB”:

1. SpringBoot MongoDB RestAPIs:

SpringBoot-MongoDB-RestAPIs

2. Angular CRUD Application:

Angular-CRUD-Application

– GitHub Sourcecode:

SpringBoot MongoDB CRUD RestAPI Example

Angular CRUD Application

Leave a Reply

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