Angular 6 HttpClient – PostgreSQL – Node.js/Express Sequelize CRUD APIs – Post/Get/Put/Delete

angular-6-httpclient-postgresql-node-js-express-sequelize-crud-apis-post-get-put-delete-feature-image

Sequelize is a promise-based ORM for Node.js v4 and later. In the tutorial, we will show how to GET/POST/PUT/DELETE requests from Angular 6 Client to PostgreSQL with NodeJs/Express RestAPIs using Sequelize ORM.

Related posts:
Node.js/Express RestAPIs CRUD – Sequelize ORM – PostgreSQL
Node.js/Express RestAPIs – Angular 6 HttpClient – Get/Post/Put/Delete requests + Bootstrap 4

Technologies

  • Angular 6
  • RxJS 6
  • Bootstrap 4
  • Visual Studio Code – version 1.24.0
  • Nodejs – v8.11.3
  • Sequelize
  • PostgreSQL

Demo

Overview

Goal

We create 2 projects:

– Angular Client Project:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + angular-project-structure

– Node.js RestAPIs project:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + nodejs-project-structure

UserCase

Start Node.js server -> Logs:


App listening at http://:::8080
Executing (default): DROP TABLE IF EXISTS "customers" CASCADE;
Executing (default): DROP TABLE IF EXISTS "customers" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "customers" ("id"   SERIAL , "firstname" VARCHAR(255), "lastname" VARCHAR(255), "age" INTEGER, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'customers' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Drop and Resync with { force: true }
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Joe','Thomas',36,'2018-07-11 08:31:06.976 +00:00','2018-07-11 08:31:06.976 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Peter','Smith',18,'2018-07-11 08:31:06.977 +00:00','2018-07-11 08:31:06.977 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Lauren','Taylor',31,'2018-07-11 08:31:06.978 +00:00','2018-07-11 08:31:06.978 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Mary','Taylor',24,'2018-07-11 08:31:06.978 +00:00','2018-07-11 08:31:06.978 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'David','Moore',25,'2018-07-11 08:31:06.978 +00:00','2018-07-11 08:31:06.978 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Holly','Davies',27,'2018-07-11 08:31:06.978 +00:00','2018-07-11 08:31:06.978 +00:00') RETURNING *;
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Michael','Brown',45,'2018-07-11 08:31:06.979 +00:00','2018-07-11 08:31:06.979 +00:00') RETURNING *;

-> PostgreSQL records:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + initial-data-postgresql-records

– Angular client retrieve all customers from Node.js RestAPIs:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + retrieve-all

– Angular client update a customer -> Change the firstname of first customer: ‘Joe’ to ‘Robert’.

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + update-form

-> result:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + update-result

– Delete ‘Peter’ customer:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + delete-result

– Add a new customer:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + add-new

-> result:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + add-result

– Check final customer’s list:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + check-final-list

-> Sequelize Logs:


Executing (default): SELECT "id", "firstname", "lastname", "age", "createdAt", "updatedAt" FROM "customers" AS "customer";
Executing (default): SELECT "id", "firstname", "lastname", "age", "createdAt", "updatedAt" FROM "customers" AS "customer" WHERE "customer"."id" = '1';
Executing (default): UPDATE "customers" SET "id"=1,"firstname"='Robert',"lastname"='Thomas',"age"=36,"createdAt"='2018-07-11 08:31:06.976 +00:00',"updatedAt"='2018-07-11 08:32:42.344 +00:00' WHERE "id" = 1
Executing (default): SELECT "id", "firstname", "lastname", "age", "createdAt", "updatedAt" FROM "customers" AS "customer";
Executing (default): SELECT "id", "firstname", "lastname", "age", "createdAt", "updatedAt" FROM "customers" AS "customer" WHERE "customer"."id" = '2';
Executing (default): DELETE FROM "customers" WHERE "id" = '2'
Executing (default): SELECT "id", "firstname", "lastname", "age", "createdAt", "updatedAt" FROM "customers" AS "customer";
Executing (default): INSERT INTO "customers" ("id","firstname","lastname","age","createdAt","updatedAt") VALUES (DEFAULT,'Maria','Garcia',39,'2018-07-11 08:33:04.390 +00:00','2018-07-11 08:33:04.390 +00:00') RETURNING *;

-> PostgreSQL’s records:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + fina-postgresql-records

Node.js/Express RestAPIs

Node.js exposes 5 RestAPIs as below:

  • router.post(‘/api/customers’, customers.create);
  • router.get(‘/api/customers’, customers.findAll);
  • router.get(‘/api/customers/:id’, customers.findOne);
  • router.put(‘/api/customers’, customers.update);
  • router.delete(‘/api/customers/:id’, customers.delete);

– Configure cross-origin for Angular-Client which running at port: 4200.


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

Angular 6 HttpClient

Use Angular HttpClient APIs to do Get/Post/Put/Delete requests to Node.js RestAPIs:

// 1. GET All Customers from remote SpringBoot API <code>@GetMapping(value="/api/customers")
getCustomers (): Observable<Customer[]> {
	return this.http.get<Customer[]>(this.customersUrl)
}
 
// 2. GET a Customer from remote SpringBoot API <code>@GetMapping(value="/api/customers/{id}")
getCustomer(id: number): Observable<Customer> {
	const url = `${this.customersUrl}/${id}`;
	return this.http.get<Customer>(url);
}
 
// 3. POST a Customer to remote SpringBoot API <code>@PostMapping(value="/api/customers")
addCustomer (customer: Customer): Observable<Customer> {
	return this.http.post<Customer>(this.customersUrl, customer, httpOptions);
}
 
// 4.DELETE a Customer from remote SpringBoot API <code>@DeleteMapping(value="/api/customers/{id}")
deleteCustomer (customer: Customer | number): Observable<Customer> {
	const id = typeof customer === 'number' ? customer : customer.id;
	const url = `${this.customersUrl}/${id}`;
 
	return this.http.delete<Customer>(url, httpOptions);
}
 
// 5. PUT a Customer to remote SpringBoot API <code>@PutMapping(value="/api/customers")
updateCustomer (customer: Customer): Observable<any> {
	return this.http.put(this.customersUrl, customer, httpOptions);
}

Practice

Node.js Express RestAPIs

Setting up NodeJs/Express project

Following the guide to create a NodeJS/Express project.

Install Express, Sequelize, PostgreSQL, and Cors:


$npm install express sequelize pg pg-hstore cors --save

– Express is one of the most popular web frameworks for NodeJs which is built on top of Node.js http module, and adds support for routing, middleware, view system etc.
– Cors is a mechanism that uses HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.
– Sequelize is a promise-based ORM for Node.js v4 and up. It supports the dialects PostgreSQL, MySQL …

-> package.json file:


{
  "name": "nodejs-express-sequelizejs-postgresql",
  "version": "1.0.0",
  "description": "nodejs-express-sequelizejs-postgresql",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "Angular-6-Client-NodeJs-Express-RestAPIs-SequelizeJs-CRUD-PostgreSQL"
  ],
  "author": "JSA",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.4",
    "express": "^4.16.3",
    "pg": "^7.4.3",
    "pg-hstore": "^2.3.2",
    "sequelize": "^4.37.6"
  }
}

Setting up Sequelize PostgreSQL connection

– Create ‘./app/config/env.js’ file:


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

– Setup Sequelize-PostgreSQL connection in ‘./app/config/db.config.js’ file:


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;
 
//Models/tables
db.customers = require('../model/customer.model.js')(sequelize, Sequelize);
 
module.exports = db;

Create Sequelize model

Create file ./app/model/customer.model.js file:


module.exports = (sequelize, Sequelize) => {
	const Customer = sequelize.define('customer', {
	  firstname: {
		type: Sequelize.STRING
	  },
	  lastname: {
		type: Sequelize.STRING
	  },
	  age: {
		  type: Sequelize.INTEGER
	  }
	});
	
	return Customer;
}

Express RestAPIs

Route ->
Define Customer’s routes in ‘./app/controller/customer.route.js’ file:


module.exports = function(app) {
    const customers = require('../controller/customer.controller.js');
 
    // Create a new Customer
    app.post('/api/customers', customers.create);
 
    // Retrieve all Customer
    app.get('/api/customers', customers.findAll);
 
    // Retrieve a single Customer by Id
    app.get('/api/customers/:id', customers.findById);
 
    // Update a Customer with Id
    app.put('/api/customers', customers.update);
 
    // Delete a Customer with Id
    app.delete('/api/customers/:id', customers.delete);
}

Controller
Implement Customer’s controller in ‘./app/controller/customer.controller.js’ file:


const db = require('../config/db.config.js');
const Customer = db.customers;

// Post a Customer
exports.create = (req, res) => {	
	// Save to PostgreSQL database
	Customer.create({
				"firstname": req.body.firstname, 
				"lastname": req.body.lastname, 
				"age": req.body.age
			}).then(customer => {		
			// Send created customer to client
			res.json(customer);
		}).catch(err => {
			console.log(err);
			res.status(500).json({msg: "error", details: err});
		});
};
 
// FETCH All Customers
exports.findAll = (req, res) => {
	Customer.findAll().then(customers => {
			// Send All Customers to Client
			res.json(customers.sort(function(c1, c2){return c1.id - c2.id}));
		}).catch(err => {
			console.log(err);
			res.status(500).json({msg: "error", details: err});
		});
};

// Find a Customer by Id
exports.findById = (req, res) => {	
	Customer.findById(req.params.id).then(customer => {
			res.json(customer);
		}).catch(err => {
			console.log(err);
			res.status(500).json({msg: "error", details: err});
		});
};
 
// Update a Customer
exports.update = (req, res) => {
	const id = req.body.id;
	Customer.update( req.body, 
			{ where: {id: id} }).then(() => {
				res.status(200).json( { mgs: "Updated Successfully -> Customer Id = " + id } );
			}).catch(err => {
				console.log(err);
				res.status(500).json({msg: "error", details: err});
			});
};

// Delete a Customer by Id
exports.delete = (req, res) => {
	const id = req.params.id;
	Customer.destroy({
			where: { id: id }
		}).then(() => {
			res.status(200).json( { msg: 'Deleted Successfully -> Customer Id = ' + id } );
		}).catch(err => {
			console.log(err);
			res.status(500).json({msg: "error", details: err});
		});
};

Server.js

server.js ->


var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json())
 
const cors = require('cors')
const corsOptions = {
  origin: 'http://localhost:4200',
  optionsSuccessStatus: 200
}
 
app.use(cors(corsOptions))
 
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 }');
  initial();
});
 
require('./app/route/customer.route.js')(app);
 
// Create a Server
var 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);
})
 
function initial(){
 
  let customers = [
    {
      firstname: "Joe",
      lastname: "Thomas",
      age: 36
    },
    {
      firstname: "Peter",
      lastname: "Smith",
      age: 18
    },
    {
      firstname: "Lauren",
      lastname: "Taylor",
      age: 31
    },
    {
      firstname: "Mary",
      lastname: "Taylor",
      age: 24
    },
    {
      firstname: "David",
      lastname: "Moore",
      age: 25
    },
    {
      firstname: "Holly",
      lastname: "Davies",
      age: 27
    },
    {
      firstname: "Michael",
      lastname: "Brown",
      age: 45
    }
  ]
 
  // Init data -> save to PostgreSQL
  const Customer = db.customers;
  for (let i = 0; i < customers.length; i++) { 
    Customer.create(customers[i]);  
  }
}

Angular 6 Client

Data Model

customer.ts ->


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

Configure AppModule

In the developed application, we use:

  • Angular Forms -> for building form
  • HttpClient -> for http Get/Post/Put/Delete requests
  • AppRouting -> for app routing

-> Modify AppModule app.module.ts:


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { FormsModule }   from '@angular/forms';
import { HttpClientModule }    from '@angular/common/http';
 
import { AppRoutingModule }     from './app-routing/app-routing.module';
 
import { AppComponent } from './app.component';
import { CustomerComponent } from './customer/customer.component';
import { CustomerDetailsComponent } from './customer-details/customer-details.component';
import { AddCustomerComponent } from './add-customer/add-customer.component';
 
@NgModule({
  declarations: [
    AppComponent,
    CustomerComponent,
    CustomerDetailsComponent,
    AddCustomerComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

HttpClient DataService

Implement CustomerService customer.service.ts with HttpClient for Get/Post/Put/Delete:


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Customer } from './customer';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable({
  providedIn: 'root'
})
export class CustomerService {
  private customersUrl = 'http://localhost:8080/api/customers';  // URL to web api
  constructor( 
    private http: HttpClient
  ) { }

  getCustomers (): Observable {
    return this.http.get(this.customersUrl)
  }

  getCustomer(id: number): Observable {
    const url = `${this.customersUrl}/${id}`;
    return this.http.get(url);
  }

  addCustomer (customer: Customer): Observable {
    return this.http.post(this.customersUrl, customer, httpOptions);
  }

  deleteCustomer (customer: Customer | number): Observable {
    const id = typeof customer === 'number' ? customer : customer.id;
    const url = `${this.customersUrl}/${id}`;

    return this.http.delete(url, httpOptions);
  }

  updateCustomer (customer: Customer): Observable {
    return this.http.put(this.customersUrl, customer, httpOptions);
  }
}

Angular Router

Implement App-Routing module app-routing.module.ts:


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomerComponent } from '../customer/customer.component';
import { AddCustomerComponent } from '../add-customer/add-customer.component';
import { CustomerDetailsComponent } from '../customer-details/customer-details.component';
 
const routes: Routes = [
   { 
     path: 'customers', 
     component: CustomerComponent 
   },
   { 
     path: 'customer/add', 
     component: AddCustomerComponent 
   },
   { 
     path: 'customers/:id', 
     component: CustomerDetailsComponent 
   },
   { 
     path: '', 
     redirectTo: 'customers', 
     pathMatch: 'full'
   }, 
];
 
@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
 
export class AppRoutingModule {}

Router Outlet & Router Links

-> Questions:

  • How to show Componenets with Angular Routers? -> Solution: using Router Outlet
  • How to handle the routing that comes from user’s actions? (like clicks on anchor tag) -> Solution: using Router Link

-> We can achieve above functions by using Angular’s router-outlet and routerLink.

Modify the template file app.component.html of AppComponenet component as below:

<div class="container">
  <div class="row">
    <div class="col-sm-4">  
      <h1>Angular HttpClient</h1>
      <ul class="nav justify-content-center">
          <li class="nav-item">
              <a routerLink="customers" class="btn btn-light btn-sm" role="button" routerLinkActive="active">Retrieve</a> 
          </li>
          <li class="nav-item">
              <a routerLink="customer/add" class="btn btn-light btn-sm" role="button" routerLinkActive="active">Create</a>
          </li>
      </ul>
      <hr>
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

Customer Component

Customer Component ->

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + retrieve-all

– Implement CustomerComponent class customer.component.ts:


import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';
 
 
@Component({
  selector: 'app-customer',
  templateUrl: './customer.component.html',
  styleUrls: ['./customer.component.css']
})
 
export class CustomerComponent  implements OnInit {
 
  customers: Customer[];
 
  constructor(private customerService: CustomerService) {}
 
  ngOnInit(): void {
     this.getCustomers();
  }
 
  getCustomers() {
    return this.customerService.getCustomers()
               .subscribe(
                 customers => {
                  console.log(customers);
                  this.customers = customers
                 }
                );
 }
}

– Implement the template customer.component.html :

<h5>All Customers</h5>
<div *ngFor="let cust of customers">
  <a [routerLink]="['/customers', cust.id]" style="color:black"><span class="badge badge-dark">{{cust.id}}</span> -> {{ cust.firstname }}</a>
</div>

Customer Detail Component

Customer Detail ->

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + update-form

-> results:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + update-result

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + delete-result

– Implement CustomerDetails class customer-details.component.ts:


import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';
 
import { ActivatedRoute, Params } from '@angular/router';
import { Location } from '@angular/common';
 
@Component({
  selector: 'app-customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
})
export class CustomerDetailsComponent implements OnInit {
 
  customer = new Customer() ;
  submitted = false;
  message: string;
 
  constructor(
    private customerService: CustomerService,
    private route: ActivatedRoute,
    private location: Location
  ) {}
 
  ngOnInit(): void {
    const id = +this.route.snapshot.paramMap.get('id');
    this.customerService.getCustomer(id)
      .subscribe(customer => this.customer = customer);
  }
 
  update(): void {
    this.submitted = true;
    this.customerService.updateCustomer(this.customer)
        .subscribe(() => this.message = "Customer Updated Successfully!");
  }
 
  delete(): void {
    this.submitted = true;
    this.customerService.deleteCustomer(this.customer.id)
        .subscribe(()=> this.message = "Customer Deleted Successfully!");
  }
 
  goBack(): void {
    this.location.back();
  }
}

– Implement CustomerDetailsComponent template customer-details.component.html :

<h4><span class="badge badge-light ">{{customer.id}}</span> -> {{customer.firstname}}</h4>
<div [hidden]="submitted">
    <form  #detailCustomerForm="ngForm">
      <div class="form-group">
        <label for="firstname">First Name</label>
        <input type="text" class="form-control" id="firstname" required
        [(ngModel)]="customer.firstname" name="firstname" #firstname="ngModel">
        <div [hidden]="firstname.valid || firstname.pristine"
             class="alert alert-danger">
            First Name is required
        </div>
      </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" #lastname="ngModel">
        <div [hidden]="lastname.valid || lastname.pristine"
             class="alert alert-danger">
            Last Name is required
        </div>
      </div>
      
      <div class="form-group">
        <label for="age">Age</label>
        <input type="number" class="form-control" id="age" required
        [(ngModel)]="customer.age" name="age" #age="ngModel">
        <div [hidden]="age.valid || age.pristine"
             class="alert alert-danger">
            Age is required
        </div>
      </div>

      <div class="btn-group btn-group-sm">
        <button type="button" class="btn btn-dark" (click)="goBack()">Back</button>
        <button type="button" class="btn btn-dark" (click)="update()" [disabled]="!detailCustomerForm.form.valid">Update</button>
        <button type="button" class="btn btn-dark" (click)="delete()">Delete</button>
	    </div>
    </form>
</div>
 
<div [hidden]="!submitted">
    <p>{{message}}</p>
    <div class="btn-group btn-group-sm">
      <button type="button" class="btn btn-dark" (click)="goBack()">Back</button>
    </div>
</div>

We can change the value of ng-valid & ng-invalid for more visual feedback,
-> Create ./assets/forms.css file:


.ng-valid[required], .ng-valid.required  {
    border-left: 5px solid rgba(32, 77, 32, 0.623);
}
 
.ng-invalid:not(form)  {
    border-left: 5px solid rgb(148, 27, 27);
}

Add ./assets/forms.css file to index.html :

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Angular6Httpclient</title>
  <base href="/">
 
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="assets/forms.css">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Add-Customer Component

AddCustomer Component ->

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + add-new

-> result:

angular-6-http-client-nodejs-express-sequelize-crud-postgresql + add-result

– Implement AddCustomerComponent class add-customer.component.ts:


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

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

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

export class AddCustomerComponent{

  customer = new Customer();
  submitted = false;

  constructor(
    private customerService: CustomerService,
    private location: Location
  ) { }

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

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

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

  private save(): void {
    this.customerService.addCustomer(this.customer)
        .subscribe();
  }
}

– Implement the template add-customer.component.html:

<h3>Add Customer</h3>
<div [hidden]="submitted">
    <form #addCustomerForm="ngForm">

      <div class="form-group">
        <label for="firstname">First Name</label>
        <input type="text" class="form-control" id="firstname" placeholder="Give Customer's FirstName" 
        required
        [(ngModel)]="customer.firstname" name="firstname" #firstname="ngModel">
        <div [hidden]="firstname.valid || firstname.pristine"
             class="alert alert-danger">
            First Name is required
        </div>
      </div>
      
      <div class="form-group">
        <label for="lastname">Last Name</label>
        <input type="text" class="form-control" id="lastname" placeholder="Give Customer's LastName"
        required
        [(ngModel)]="customer.lastname" name="lastname" #lastname="ngModel">
        <div [hidden]="lastname.valid || lastname.pristine"
             class="alert alert-danger">
            Last Name is required
        </div>
      </div>
      
      <div class="form-group">
        <label for="age">Age</label>
        <input type="number" class="form-control" id="age" 
        placeholder="Give Customer's Age"
        required
        [(ngModel)]="customer.age" name="age" #age="ngModel">
        <div [hidden]="age.valid || age.pristine"
             class="alert alert-danger">
            Age is required
        </div>
      </div>
      
      <div class="btn-group btn-group-sm">
      	<button type="button" class="btn btn-dark" (click)="goBack()">Back</button>
      	<button type="button" class="btn btn-dark" (click)="addCustomer()" [disabled]="!addCustomerForm.form.valid">Add</button>
      </div>
    </form>
</div>

<div [hidden]="!submitted">
  <p>Submitted Successfully! -> <span class="badge badge-light">{{customer.firstname}}  {{customer.lastname}}</span></p>
	<div class="btn-group btn-group-sm">
    	<button type="button" class="btn btn-dark" (click)="goBack()">Back</button>
    	<button type="button" class="btn btn-dark" (click)="newCustomer(); addCustomerForm.reset()">Continue</button>
    </div>
</div>

SourceCode

- Angular-6-Http-Client
- Nodejs-Express-Sequelizejs-PostgreSQL

198 thoughts on “Angular 6 HttpClient – PostgreSQL – Node.js/Express Sequelize CRUD APIs – Post/Get/Put/Delete”

  1. i created one more table called login in server.js file. Happily table was created in database now i want to display that table how you displayed customers table in reterive coloumn . I had created one more component called login and i created routing also and how i can display both customers and login in same host “8080”. i created seperate service for login. When i display both tables in same host i got this type of error follows

    ” message: “Http failure response for http://localhost:8080/api/login: 404 Not Found”

    name: “HttpErrorResponse” “

  2. Dear, could you explain to me, how the customers table is created, when npm server is executed, I do not see the code to create it in the example, greetings

  3. Hey Francisco Gomez, Thanks for your code. But I didn’t understood how it is dropping and creating the table Users. nowhere you mentioned the create, drop, insert and select queries in your code.
    I have tried changing the schema of the table, but when I rerun the server, again it is creating the table with the previous values only.

  4. Somebody essentially lend a hand to make seriously articles I might state.
    This is the very first time I frequented your web page and up to
    now? I surprised with the research you made to create
    this actual submit incredible. Excellent activity!

  5. I came across your website the previous week and i has become going through it’s on the regular basis. There are any a number of tips appropriate so i really love look within the online store at the same time. Continue monetary management be effective!

  6. What i do not realize is actually how you are no longer really a lot more neatly-appreciated than you might be right now. You’re very intelligent. You recognize thus considerably in terms of this matter, produced me individually consider it from numerous varied angles. Its like men and women are not interested until it is one thing to do with Lady gaga! Your own stuffs excellent. Always maintain it up!

  7. Excellent website right here! Additionally your website starts up very fast! What host are you using? Can you pass along your affiliate hyperlink to your host? I desire my site loaded up as quickly as yours lol

  8. I have to express my appreciation for your generosity in support of women who really want help on in this concern. Your personal commitment to getting the message around appeared to be especially beneficial and have specifically made regular people like me to attain their endeavors. The interesting help signifies a lot to me and much more to my fellow workers. Thanks a ton; from each one of us.

  9. I would like to show my thanks to this writer for rescuing me from such a instance. Because of looking throughout the world-wide-web and getting opinions which are not beneficial, I figured my life was well over. Living without the presence of solutions to the difficulties you have fixed as a result of your good short article is a critical case, and the kind which might have in a negative way damaged my entire career if I had not encountered your web site. Your good competence and kindness in maneuvering everything was important. I don’t know what I would’ve done if I had not encountered such a subject like this. I am able to now look ahead to my future. Thanks for your time so much for your reliable and amazing guide. I will not be reluctant to propose your blog post to any person who wants and needs guidance on this issue. [Reply]

  10. Oh my goodness! a tremendous article dude. Thanks Nevertheless I’m experiencing subject with ur rss . Don抰 know why Unable to subscribe to it. Is there anybody getting identical rss drawback? Anybody who knows kindly respond. Thnkx

  11. I got this website from my friend who told me on the topic of this
    web site and now this time I am visiting this web site and
    reading very informative content at this time.

  12. You really make it seem so easy with your presentation but I find this topic
    to be really something that I think I would never understand.
    It seems too complicated and very broad for
    me. I’m looking forward for your next post, I’ll try to get the hang of it!

  13. Magnificent goods from you, man. I have take note your stuff previous to and you are just extremely magnificent.

    I actually like what you have obtained right here, certainly like what you are stating and the way in which in which you assert it.
    You’re making it entertaining and you continue to care for to keep it wise.
    I cant wait to read much more from you. This is actually
    a tremendous site.

  14. Ꮇy developer is trying to persuade me too move to .net from
    PHP. I have always disⅼiuked the idea because of tthe expenseѕ.
    Вսt he’s tryiong none thе less. I’ve Ьeen using Movable-tyрe
    on a varety of websites for аbout a year andd am anxious about switching
    to another platform. I have heard fantastic things about
    blogengine.net. Is there a way I cаn import alll mү woгdpress posts int it?

    Any heⅼp would be gгeatly appreciated!

  15. I do trust all of the ideas you’ve introduced for
    your post. They are very convincing and will definitely work.
    Still, the posts are too short for starters. May just you please extend them
    a little from next time? Thank you for the post.

  16. Fine way of describing, and good paragraph to obtain data on the topic
    of my presentation focus, which i am going to deliver in institution of higher education.

  17. Definitely consider that which you said. Your favorite reason seemed to be on the
    web the easiest factor to take note of. I say to
    you, I certainly get annoyed while other people consider concerns that they just don’t realize about.
    You controlled to hit the nail upon the top and also defined out the whole thing without having side effect , people can take a signal.
    Will probably be back to get more. Thank you

  18. Its like you read my mind! You appear to know so much about this, like you wrote the
    book in it or something. I think that you could do with some pics to
    drive the message home a little bit, but other than that, this is excellent blog.
    A fantastic read. I will certainly be back.

  19. An impressive share! I have just forwarded this onto a colleague who has been conducting
    a little homework on this. And he actually bought me breakfast due
    to the fact that I discovered it for him… lol. So let me reword this….

    Thanks for the meal!! But yeah, thanx for spending some time to talk about this issue here on your
    web site.

  20. Oh my goodness! Incredible article dude! Thank you so much, However I am going through issues with your RSS.
    I don’t know the reason why I cannot subscribe to it. Is there anybody else
    getting identical RSS problems? Anyone who knows the solution will you kindly respond?
    Thanx!!

  21. Hey there, I think your blog might be having browser compatibility issues.

    When I look at your website in Firefox, it looks fine but when opening in Internet Explorer, it
    has some overlapping. I just wanted to give you a quick heads up!
    Other then that, terrific blog!

  22. You really make it seem so easy with your presentation but I find this matter to be really something that I think I would never understand.
    It seems too complex and very broad for me. I’m looking forward for your next post,
    I will try to get the hang of it!

  23. Hello! I realize this is sort of off-topic however I had to
    ask. Does managing a well-established blog like yours take
    a large amount of work? I’m completely new to writing a blog but I do write
    in my journal every day. I’d like to start a blog so I will
    be able to share my experience and feelings online. Please let me know if you have any recommendations or tips for brand new aspiring blog owners.

    Thankyou!

  24. Aw, this was an exceptionally good post. Spending some time and actual
    effort to create a superb article… but what can I say… I hesitate a
    whole lot and never seem to get nearly anything done.

  25. Hey there! Would you mind if I share your blog with
    my facebook group? There’s a lot of folks that I think would really enjoy
    your content. Please let me know. Many thanks

  26. We are a bunch of volunteers and opening a brand new scheme in our community.
    Your web site provided us with valuable info to work on. You have performed a formidable process and our entire
    group will likely be thankful to you.

  27. Awesome blog! Do you have any tips and hints for aspiring writers?
    I’m planning to start my own site soon but I’m a little lost
    on everything. Would you recommend starting with a free platform like WordPress or
    go for a paid option? There are so many options out
    there that I’m totally overwhelmed .. Any ideas?
    Thank you!

  28. Heya i am for the first time here. I came across this board and
    I find It truly useful & it helped me out a lot.
    I hope to give something back and help others like you aided me.

  29. Excellent blog here! Also your website loads up very fast!
    What host are you using? Can I get your affiliate
    link to your host? I wish my site loaded up as quickly as yours lol

  30. My programmer is trying to persuade me to move to .net from PHP.
    I have always disliked the idea because of the costs.
    But he’s tryiong none the less. I’ve been using WordPress on a variety of
    websites for about a year and am anxious about switching to another platform.
    I have heard very good things about blogengine.net.
    Is there a way I can transfer all my wordpress
    posts into it? Any help would be greatly appreciated!

  31. Hi there! Do you know if they make any plugins to help with Search Engine
    Optimization? I’m trying to get my blog to rank for some targeted keywords but
    I’m not seeing very good success. If you know of any please share.
    Appreciate it!

  32. My brother suggested I might like this website.

    He was once entirely right. This post truly made
    my day. You can not consider simply how a lot time
    I had spent for this information! Thank you!

  33. You could definitely see your expertise in the work you write.

    The arena hopes for more passionate writers like you who aren’t afraid to say how they believe.

    All the time go after your heart.

  34. I know this if off topic but I’m looking into starting my own blog and was wondering what
    all is required to get set up? I’m assuming having a blog like yours would
    cost a pretty penny? I’m not very web savvy so I’m not 100% sure.
    Any recommendations or advice would be greatly appreciated.
    Many thanks

  35. Pretty nice post. I just stumbled upon your blog and wished to say that I’ve really enjoyed surfing around your blog posts.
    After all I’ll be subscribing to your feed and I hope you write
    again very soon!

  36. I simply couldn’t leave your web site prior to suggesting that I extremely
    enjoyed the standard info an individual provide to your
    visitors? Is going to be back regularly to investigate cross-check new posts

  37. I’m more than happy to discover this page. I need to to thank you for ones time due to this wonderful read!!
    I definitely appreciated every little bit of it and i also have you bookmarked to check out new stuff on your site.

  38. Hi, I think your blog might be having browser compatibility issues.
    When I look at your blog site in Firefox, it looks fine but when opening in Internet
    Explorer, it has some overlapping. I just wanted to
    give you a quick heads up! Other then that, superb blog!

  39. Simply want to say your article is as astonishing.

    The clearness in your post is just excellent and i can assume you are
    an expert on this subject. Well with your permission allow me to grab your RSS feed to keep up to date with forthcoming post.
    Thanks a million and please carry on the gratifying
    work.

  40. It’s truly very complex in this active life to listen news on Television, thus I just use internet for that reason, and get the
    latest information.

  41. Your style is very unique in comparison to other people I have read stuff from.
    Thanks for posting when you have the opportunity, Guess I’ll just
    bookmark this blog.

  42. Hey there! I know this is kinda off topic however , I’d figured I’d ask.

    Would you be interested in exchanging links
    or maybe guest writing a blog post or vice-versa?
    My blog addresses a lot of the same topics as yours and I think we could
    greatly benefit from each other. If you’re interested feel
    free to shoot me an email. I look forward to hearing
    from you! Fantastic blog by the way!

  43. Hello, Neat post. There is an issue with your site in internet explorer, may
    check this? IE nonetheless is the market chief and a large element of people will leave out your great
    writing because of this problem.

  44. Howdy, i read your blog from time to time and i own a similar one and i was
    just wondering if you get a lot of spam remarks? If so how do you stop it,
    any plugin or anything you can advise? I get
    so much lately it’s driving me mad so any support is
    very much appreciated.

  45. I am not sure where you’re getting your information, but great
    topic. I needs to spend some time learning much more or understanding more.

    Thanks for fantastic information I was looking for this info for my mission.

  46. Just wish to say your article is as astounding. The clarity on your submit is simply spectacular and i could
    think you’re a professional in this subject. Well along with your permission allow me to
    seize your feed to stay updated with imminent post. Thank you a million and please carry on the enjoyable work.

  47. I believe what you published was actually very
    logical. But, what about this? what if you typed a catchier title?
    I am not saying your content is not solid, however suppose you added a post title that grabbed a person’s attention? I mean ozenero | Mobile &
    Web Programming Tutorials is a little vanilla. You might glance at Yahoo’s
    home page and note how they create post titles to get people interested.
    You might try adding a video or a pic or two
    to get readers excited about everything’ve got to say. Just
    my opinion, it would make your website a little bit more interesting.

  48. I simply could not leave your web site prior to suggesting that I really loved the usual info an individual provide
    on your visitors? Is gonna be again ceaselessly to investigate cross-check
    new posts

  49. Helpful information. Fortunate me I found your website by chance, and I am shocked
    why this twist of fate didn’t took place in advance!
    I bookmarked it.

  50. Howdy just wanted to give you a quick heads up and let
    you know a few of the pictures aren’t loading
    correctly. I’m not sure why but I think its a linking issue.
    I’ve tried it in two different internet browsers and both show the same results.

  51. I’m gone to inform my little brother, that he should also pay a visit this
    webpage on regular basis to obtain updated from most up-to-date news update.

  52. Hey! I just wanted to ask if you ever have any problems with hackers?
    My last blog (wordpress) was hacked and I ended up losing months of
    hard work due to no back up. Do you have any methods to stop hackers?

  53. Undeniably consider that that you stated. Your favourite reason seemed to be on the net the easiest thing to have in mind of.
    I say to you, I definitely get irked while other folks think about worries that they plainly do not recognise about.
    You controlled to hit the nail upon the highest and also defined out the whole thing with no
    need side effect , people could take a signal. Will likely
    be again to get more. Thank you

  54. Having read this I believed it was extremely enlightening.
    I appreciate you finding the time and energy to put this information together.
    I once again find myself spending way too much time both
    reading and leaving comments. But so what, it was still worth it!

  55. I’m extremely pleased to find this page. I need to to thank you for ones time for this particularly fantastic read!!

    I definitely savored every little bit of it and I have you book marked to check out new things on your website.

  56. Write more, thats all I have to say. Literally, it
    seems as though you relied on the video to make your point.
    You obviously know what youre talking about, why
    waste your intelligence on just posting videos to your blog when you could be giving us
    something informative to read?

  57. It’s truly a great and useful piece of info.
    I’m happy that you just shared this helpful information with
    us. Please keep us informed like this. Thanks for sharing.

  58. No matter if some one searches for his required thing, therefore he/she needs to be available that in detail, thus that thing is maintained over here.

  59. Hello there! This is kind of off topic but I need some guidance from an established blog.
    Is it very hard to set up your own blog? I’m not very techincal but I can figure things out pretty fast.
    I’m thinking about making my own but I’m not sure where
    to begin. Do you have any points or suggestions?
    With thanks

  60. Just wish to say your article is as amazing. The clarity for your put up
    is simply great and i can assume you are an expert in this subject.
    Well with your permission allow me to take hold of your RSS
    feed to stay up to date with impending post. Thank you one million and please carry on the enjoyable work.

  61. Just desire to say your article is as amazing. The clarity in your post
    is just cool and i could assume you are an expert on this subject.

    Well with your permission allow me to grab your feed
    to keep up to date with forthcoming post. Thanks a million and please keep up the gratifying work.

  62. I do not know whether it’s just me or if perhaps everybody else
    encountering problems with your website. It appears like some of
    the written text on your posts are running off the screen. Can somebody else please comment and let
    me know if this is happening to them as well? This might be a problem with my web browser because I’ve had this happen before.

    Kudos

  63. A person necessarily help to make critically posts I would state.

    This is the first time I frequented your website page and thus far?
    I surprised with the analysis you made to create this particular submit incredible.
    Great job!

  64. I like the valuable info you provide in your articles. I will bookmark your weblog and check again here frequently.

    I’m quite sure I will learn many new stuff right here!
    Best of luck for the next!

  65. I simply could not go away your web site before suggesting that I actually enjoyed
    the standard info an individual provide on your
    guests? Is gonna be back regularly in order to inspect new posts

  66. Hey! Do you know if they make any plugins to assist with SEO?
    I’m trying to get my blog to rank for some targeted keywords but
    I’m not seeing very good gains. If you know of any please share.
    Cheers!

  67. Hi there, just became alert to your blog through Google, and found that it is truly informative.
    I’m gonna watch out for brussels. I will be grateful if you continue this in future.
    Lots of people will be benefited from your writing.

    Cheers!

  68. I like the helpful info you provide in your articles. I will bookmark your blog and check
    again here frequently. I’m quite certain I will learn plenty of new stuff right here!
    Best of luck for the next!

  69. Nice post. I learn something new and challenging on blogs I stumbleupon on a
    daily basis. It’s always exciting to read through content from other writers and use something from other websites.

  70. Thank you for every other excellent article. Where else may anyone get that kind of info in such an ideal approach of writing?
    I have a presentation next week, and I am on the
    look for such info.

  71. My developer is trying to convince me to move to .net from PHP.
    I have always disliked the idea because of the expenses. But he’s tryiong none the less.
    I’ve been using Movable-type on a variety of websites
    for about a year and am worried about switching to another
    platform. I have heard fantastic things about blogengine.net.
    Is there a way I can import all my wordpress content into it?
    Any kind of help would be greatly appreciated!

  72. An outstanding share! I have just forwarded this onto a co-worker who has been doing a little research on this.
    And he actually ordered me lunch simply because I found it for him…

    lol. So allow me to reword this…. Thanks for the meal!!

    But yeah, thanks for spending time to discuss this subject here on your blog.

  73. magnificent submit, very informative. I’m wondering why the other experts of this sector don’t understand this.
    You must proceed your writing. I’m confident,
    you have a great readers’ base already!

  74. After looking over a few of the blog posts on your web page, I honestly appreciate your technique of writing a blog.
    I saved as a favorite it to my bookmark website list
    and will be checking back in the near future. Please visit
    my website as well and let me know what you think.

Leave a Reply

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