Angular 11 Node.js Mysql Crud Example

Angular-Nodejs-CRUD-MySQL-Example

Tutorial: “Angular 11 Node.js Mysql Crud Example – using Express and Sequelize ORM”

In the tutorial, I introduce how to build an Angular 11 Node.js MySQL CRUD Example RestAPIs Fullstack Project with the help of Express Web Framework and Sequelize ORM for POST/GET/PUT/DELETE requests with step by step coding examples.

Related posts:


Architecture for Angular 11 Node.js MySQL CRUD Example Fullstack

Angular 11 Node.js MySQL CRUD Example - Fullstack Angular 11 Node.js MySQL CRUD Example Application - Overview Architecture
Fullstack Angular Nodejs CRUD Application – Overview Architecture
  • We build backend Nodejs Application that provides RestAPIs for POST/GET/PUT/DELETE Customer entities and store them in MySQL/PostgreSQL database.
  • We implement Angular Application that use Angular HTTPClient to interact (call/receive requests) with SpringBoot backend and display corresponding page view in browser.

Nodejs CRUD RestAPIs Design

Nodejs-Build-CRUD-Application-Architecture-Overview
Nodejs-Build-CRUD-Application-Architecture-Overview

We have 4 main blocks for backend Node.js application:

  • For building RestAPIs in Node.js application, we use Express framework.
  • For interacting with database MySQL/PostgreSQL, we use Sequelize ORM.
  • We define APIs URL in router.js file
  • We implement how to process each API URL in controller.js file
  • We use Bootstrap and JQuery Ajax to implement frontend client.
Backend Nodejs Build Angular 11 Node.js MySQL CRUD Example - Project Structure
Backend Nodejs Build CRUD Application – Project Structure
  • config package is used to configure Sequelize and MySQL/PostgreSQL database environment
  • models package is used to define a Sequelize model to interact with database
  • routers package is used to define Rest APIs’ URL
  • controllers is used to implement business logic to processing each RestAPIs
  • views folder is used to implement HTML view pages
  • resources/js folder is used to implement JQuery Ajax to Post/Get/Put/Delete RestAPIs

Angular CRUD Design

Now I explain more about architecture of Angular application in the tutorial “Angular 11 Express MySQL CRUD Example”:

Angular 11 Node.js MySQL CRUD Example - Angular 11 Frontend Design Architecture
Angular Nodejs CRUD Application – Frontend Design Architecture

Angular CRUD Application is designed with 3 main layers:

  • Service Layer is used to define Angular Common Services and HttpClient Services to interact with RestAPIs
  • Component Layer is used to define Angular Components to show views in Browser for interacting with Users
  • Router Layer is used to route URLs mapping with the corresponding Angular Components

Angular Project Structure

Angular 11 Node.js MySQL CRUD Example - Angular Project Structure
Angular Nodejs CRUD Application – Project Structure

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

– Components:

  • add-customer component is used to add a new customer to system
  • list-customer component is used to show all customers on view pages, delete a customer and update a customer
  • message component is used to define a view to show logging message on browser

– Services:

  • customer.service.ts defines POST/GET/PUT/DELETE HTTP requests to SpringBoot RestAPIs with the built-in Angular HttpClient.
  • message.service.ts defines an array storage to log all messages when Angular CRUD App running

– 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 our application.
  • message.ts defines the response data model between SpringBoot and Angular application.

Project Goal – Angular Nodejs CRUD Example

Here is the overview project goal of the tutorial “Angular 11 Express MySQL CRUD Example”:

– Add new Customer:

Angular Nodejs CRUD App - Add New Customers
Angular Nodejs CRUD App – Add New Customers

– List All Customers:

Angular List All Customers
Angular Nodejs CRUD Application – List All Customers

– Details a Customer:

Angular Details a Customer
Angular Nodejs CRUD App – Details a Customer

– Update a Customer:

Angular Update a Customer
Angular Nodejs CRUD Application – Update a Customer

– Delete a Customer:

Angular Delete a Customer successfully
Angular Nodejs CRUD App – Delete a Customer successfully

– Check database records:

Angular 11 Check Database Records
Angular Nodejs CRUD App – Check Database Records

Video Guide – Angular 11 Node.js Mysql Crud Example

Create Nodejs CRUD RestAPIs project

For building Nodejs CRUD Application, we need to use the below dependencies:

  • body-parser is used to parse a submit form to nodejs server
  • express is used to build restApis
  • mysql2 is used for MySQL driver
  • sequelize is used to do CRUD operation with MySQL/PostgreSQL database
  • cors is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options

We install them with below commandline:


npm install --save body-parse express mysql2 sequelize cors

Check the package.json file:


{
  "name": "nodejs-build-crud-application",
  "version": "1.0.0",
  "description": "Nodejs Build Crud Application Post/Get/Put/Delete to MySQL/PostgreSQL with frontend is bootstrap framework",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "Nodejs",
    "RestAPI",
    "Express",
    "Tutorial",
    "MySQL",
    "PostgreSQL",
    "Bootstrap",
    "framework"
  ],
  "author": "https://loizenai.com",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "mysql": "^2.18.1",
    "mysql2": "^2.1.0",
    "sequelize": "^5.21.13"
  }
}

Nodejs Express Sequelize Database Configuration

We define a db.config.js file to configure Sequelize to interact with MySQL/PostgreSQL database:


const env = require('./env.js');
 
const Sequelize = require('sequelize');
const sequelize = new Sequelize(env.database, env.username, env.password, {
  host: env.host,
  dialect: env.dialect,
  operatorsAliases: false,
 
  pool: {
    max: env.max,
    min: env.pool.min,
    acquire: env.pool.acquire,
    idle: env.pool.idle
  }
});
 
const db = {};
 
db.Sequelize = Sequelize;
db.sequelize = sequelize;
 
db.Customer = require('../models/customer.model.js')(sequelize, Sequelize);
 
module.exports = db;

– For MySQL database, we add the below configured environment’s properties in env.js:

const env = {
  database: 'loizenaidb',
  username: 'root',
  password: '12345',
  host: 'localhost',
  dialect: 'mysql',
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
};
 
module.exports = env;

– For PostgreSQL database, we add the below configured environment’s properties in env.js


const env = {
  database: 'loizenai',
  username: 'postgres',
  password: '123',
  host: 'localhost',
  dialect: 'postgres',
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
};
 
module.exports = env;

Define Nodejs Sequelize Model

I create a Sequelize model customer.model.js for customer entity with 5 properties:

  • id is a primary key having INTEGER type
  • firstname property has STRING type
  • lastname property has STRING type
  • address property has STRING type
  • age property has INTEGER type
module.exports = (sequelize, Sequelize) => {
	const Customer = sequelize.define('customer', {	
	  id: {
            type: Sequelize.INTEGER,
            autoIncrement: true,
            primaryKey: true
      },
	  firstname: {
			type: Sequelize.STRING
	  },
	  lastname: {
		type: Sequelize.STRING
  	  },
	  address: {
			type: Sequelize.STRING
	  },
	  age: {
			type: Sequelize.INTEGER
	  }
	});
	
	return Customer;
}

Define Nodejs Express RestAPIs Router – POST/GET/PUT/DELETE

We define 7 APIs for 2 groups:

– Group 1 provides html page view

  • / is used to get index.html view
  • /customers/ is used to get customers.html file

– Group 2 provides RestAPIs as below:

  • /api/customer/create is POST RestAPI to POST a new customer
  • /api/customer/retrieveinfos is a GET RestAPI to retrieve all customers’ info
  • /api/customer/updatebyid/:id is a PUT RestAPI to update a customer by a given id
  • /api/customer/deletebyid/:id is a DELETE RestAPI to delete a customer by a given id

Coding:

let express = require('express');
let router = express.Router();
 
const customers = require('../controllers/controller.js');

let path = __basedir + '/view/';

router.get('/', (req,res) => {
    console.log("__basedir" + __basedir);
    res.sendFile(path + "index.html");
});

router.get('/customers/', (req,res) => {
    console.log("__basedir" + __basedir);
    res.sendFile(path + "customers.html");
});

router.post('/api/customers/create', customers.create);
router.get('/api/customers/retrieveinfos', customers.retrieveAllCustomers);
router.put('/api/customers/updatebyid/:id', customers.updateById);
router.delete('/api/customers/deletebyid/:id', customers.deleteById);

module.exports = router;

Implement Nodejs Express RestAPIs CRUD Controller

For processing Post/Get/Put/Delete RestAPI requests, we implement controller.js with 5 functions:

  • exports.create = (req, res) is used to create a new Customer (post request processing)
  • exports.retrieveInfos = (req, res) is used to retrieve all Customer’s infos (get request)
  • exports.updateById = async (req, res) is used to update a customer with a given id
  • exports.deleteById = async (req, res) is used to delete a customer with a given id

– Post request :

exports.create = (req, res) => {
    let customer = {};

    try{
        // Building Customer object from upoading request's body
        customer.firstname = req.body.firstname;
        customer.lastname = req.body.lastname;
        customer.address = req.body.address;
        customer.age = req.body.age;
    
        // Save to MySQL database
        Customer.create(customer).then(result => {    
            // send uploading message to client
            res.status(200).json({
                message: "Upload Successfully a Customer with id = " + result.id,
                customers: [result],
                error: ""
            });
        });
    }catch(error){
        res.status(500).json({
            message: "Fail!",
            customers: [],
            error: error.message
        });
    }
}

exports.create = (req, res) gets a posting customer’s info via request.body object. Then it uses Sequelize to save the customer object to database. After done, it returns a successfully posting message. Otherwise, a error message will be returned.

– Nodejs Express Sequelize Get All Customers:

exports.retrieveInfos = (req, res) => {
    // find all Customer information from 
    try{
        Customer.findAll({attributes: ['id', 'firstname', 'address']})
        .then(customerInfos => {
            res.status(200).json({
                message: "Get Customers' Infos!",
                customerInfos: customerInfos
            });
        })
    }catch(error) {
        // log on console
        console.log(error);

        res.status(500).json({
            message: "Retrieving Error!",
            error: error
        });
    }
}

The function exports.retrieveInfos = (req, res) retrieves all Customer objects from database with 5 selected attributes: id, firstname, lastname, age, address.

– Nodejs Express Sequelize Delete a Customer:

exports.deleteById = async (req, res) => {
    try{
        let customerId = req.params.id;
        let customer = await Customer.findByPk(customerId);

        if(!customer){
            res.status(404).json({
                message: "Does Not exist a Customer with id = " + customerId,
                error: "404",
                customers: []
            });
        } else {
            await customer.destroy();
            res.status(200).json({
                message: "Delete Successfully a Customer with id = " + customerId,
                customers: [customer],
                error: ""
            });
        }
    } catch(error) {
        res.status(500).json({
            message: "Error -> Can NOT delete a customer with id = " + req.params.id,
            error: error.message,
            customers: []
        });
    }
}

The function exports.deleteById = async (req, res) finds a Customer by a given id. If the customer is found, it will be deleted by destroy() function and return back client a successfully message. Otherwise, an error message is returned.

– Nodejs Express Sequelize MySQL – Update a Customer:

exports.updateById = async (req, res) => {
    try{
        let customerId = req.params.id;
        let customer = await Customer.findByPk(customerId);
    
        if(!customer){
            // return a response to client
            res.status(404).json({
                message: "Not Found for updating a customer with id = " + customerId,
                customers: [],
                error: "404"
            });
        } else {    
            // update new change to database
            let updatedObject = {
                firstname: req.body.firstname,
                lastname: req.body.lastname,
                address: req.body.address,
                age: req.body.age
            }
            let result = await Customer.update(updatedObject, {returning: true, where: {id: customerId}});
            
            // return the response to client
            if(!result) {
                res.status(500).json({
                    message: "Error -> Can not update a customer with id = " + req.params.id,
                    error: "Can NOT Updated",
                    customers: []
                });
            }

            res.status(200).json({
                message: "Update successfully a Customer with id = " + customerId,
                customers: [updatedObject],
                error: ""           
            });
        }
    } catch(error){
        res.status(500).json({
            message: "Error -> Can not update a customer with id = " + req.params.id,
            error: error.message,
            customers: []

        });
    }
}

The function exports.updateById = async (req, res) finds a customer object by a given id. If the customer is found, we change the customer attributes with new values retrieving from request.body object. After done, a successfully message will be returned. Otherwise an error message will be returned.

Create Nodejs Express Server.js

const express = require('express');
const app = express();

var bodyParser = require('body-parser');
 
global.__basedir = __dirname;
 
const db = require('./app/config/db.config.js');
  
// force: true will drop the table if it already exists
db.sequelize.sync({force: true}).then(() => {
  console.log('Drop and Resync with { force: true }');
}); 

let router = require('./app/routers/router.js');

const cors = require('cors')
const corsOptions = {
  origin: 'http://localhost:4200',
  optionsSuccessStatus: 200
}
app.use(cors(corsOptions));

app.use(bodyParser.json());
app.use(express.static('resources'));
app.use('/', router);

// Create a Server
const server = app.listen(8080, function () {
 
  let host = server.address().address
  let port = server.address().port
 
  console.log("App listening at http://%s:%s", host, port); 
})

Nodejs Express Sequelize MySQL – Backend Testing

1. Testcase 1 – Nodejs Post request – Add new Customer:

– Post a new customer:

Angular 11 Node.js MySQL CRUD Example - Backend Testing - Nodejs - Add a new customer
Backend Testing – Nodejs – Add a new customer

– Check database records:

Backend Testing - Check Database Records
Backend Testing – Check Database Records

2. Testcase 2 – Nodejs Get request – Get All Customers:

– Retrieve all customers:

Backend Testing - Nodejs - Retrieve All Customers
Backend Testing – Nodejs – Retrieve All Customers

3. Testcase 3 – Nodejs Put request – Update a Customer by Id:

– Delete a Customer with id = 3:

Angular 11 Node.js MySQL CRUD Example - Backend Testing - Nodejs - Update a Customer by id=3
Backend Testing – Nodejs – Update a Customer by id=3

4. Testcase 4 – Nodejs Delete request – Delete a Customer:

– Update a Customer with id = 2:

Angular 11 Node.js MySQL CRUD Example - Backend Testing - Nodejs - Delete a Customer by Id
Backend Testing – Nodejs – Delete a Customer by Id

Angular 11 CRUD Application Overview

Angular 11 Node.js MySQL CRUD Example - Angular Application - Frontend Design Architecture
Angular CRUD Application – Frontend Design Architecture

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

Create Angular 11 CRUD 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 Customer model

We define Customer class with 5 attributes:

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

Create Angular Message Model

We define Message class as below:

import { Customer } from './customer';

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

Implement Angular HttpClient Customer 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 – Add new Customer

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 – Retrieve Customers

– Retrieve all Customers from SpringBoot backend at RestAPI 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 – Modify a Customer

– Update a Customer with Angular 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 – Delete a Customer

– Delete a Customer by a given id with 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 proccessing in 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 = [];
  }
}

Angular 11 Implement Component: Add Customer

AddCustomerComponent is used to post a new Customer to SpringBoot backend server.
– We have 2 parts:

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

1. Implement add-customer.component.ts:

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>

Angular 11 Implement Component: List Customers

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>

Angular 11 Implement Component: 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>

Angular Configure App 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

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>

Angular 11 Modify 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>

Angular 11 Nodejs MySQL CRUD Example Application Testing

Okay, now we do a set of testcases for the tutorial: “Angular 11 Node.js MySQL CRUD Example”.

1. Testcase 1 – Angular post request – Add New Customer:

Angular Application - Testcase 1 - POST a Customer - Network Logs
Angular CRUD Application – Testcase 1 – POST a Customer – Network Logs
Angular CRUD Application - Testcase 1 - POST a Customer - Successfully
Angular CRUD Application – Testcase 1 – POST a Customer – Successfully

2. Testcase 2 – Angular get request – Retrieve All Customers:

Angular CRUD Application - Testcase 2 - GET all Customers - Network Logs
Angular CRUD Application – Testcase 2 – GET all Customers – Network Logs
Angular Application - Testcase 2 - GET all Customers - Successfully
Angular CRUD Application – Testcase 2 – GET all Customers – Successfully

3. Testcase 3 – Angular PUT request – Update a Customer:

Angular CRUD Application - Testcase 3 - UPDATE a Customer with id = 3 - Network Logs
Angular CRUD Application – Testcase 3 – UPDATE a Customer with id = 3 – Network Logs
Angular CRUD Application - Testcase 3 - UPDATE a Customer with id = 3 - Successfully
Angular CRUD Application – Testcase 3 – UPDATE a Customer with id = 3 – Successfully

4. Testcase 4 – Angular Delete request – Delete a Customer:

Angular CRUD Application - Testcase 4 - DELETE a Customer - Successfully
Angular CRUD Application – Testcase 4 – DELETE a Customer – Successfully
Angular 11 Node.js MySQL CRUD Example - Angular CRUD App - Check database records
Angular CRUD App – Check database records

Read More

Related posts:


Sourcecode – Angular 11 Node.js MySQL CRUD Example

Below is the 2 sourcecodes for “Angular 11 Node.js MySQL CRUD Example Tutorial”.

– Node.js backend’s sourcecode with below implemented features:

Nodejs CRUD Application

– GitHub Sourcecode:

Nodejs CRUD Application – Github Sourcecode

– Angular Frontend sourcecode with below implemented features:

Angular 11 Node.js Mysql Crud Example – Frontend

– Github Sourcecode – Angular 11 Express MySQL CRUD Example:

Angular 11 Node.js Mysql Crud Example – Frontend



By grokonez | February 1, 2021.


Related Posts


1 thought on “Angular 11 Node.js Mysql Crud Example”

  1. hello, thank you very much for the guide, I managed to make my crud and in testing it works great. Now I have a question, I have to put it into production, but I can’t. can you help me?

Got Something To Say:

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

*