Node JS with Sequelize ORM

Introduction

NodeJS is JavaScript run-time that executes JavaScript code outside of a browser and Sequelize is a promise-based ORM for Node.js and what the heck is ORM. ORM or Object Relation Mapping is a process of mapping between objects and relation database systems. So why use sequelize ? basicly for create , control, manipulate and manage databases with easy and fast.

If you really familiar with Node.JS , yeah Node.js is not easy if you combine with sql database , like MySQL, Postgre etc It’s really hard to manipulate data if you are using native sql syntax. So that’s why we use sequelize.

Project Intro

Ok Let’s Straigt to the point , we gonna build simple crud App with MVC Architecture in this case fruit shop, And this is technology & tools i used for :

TechnologyName
Back EndNodeJS
FrameworkExpress & Bootstrap 4
DBMSMysql
NPMMysql2 & Body Parser & Nodemon & Sequelize
Template EngineEJS
Develop Step

First create Folder and then Npm init

Second Install All Npm Package above

  • npm install –save nodemon
  • npm install –save Express
  • npm install –save Mysql2
  • npm install –save sequelize
  • npm install –save ejs

Next ,Create MVC folder schema it’s up to you for name but this is mine :

  • controller
  • models
  • routes
  • util
  • views
    • includes

Next Create server,model,require all package from app.js (our main route) :

 //Software Engineer : Faeshal Bin Sulaiman   const path = require("path");
  const express = require("express");
  const bodyParser = require("body-parser");
  const sequelize = require("./util/database");
  const adminRoutes = require("./routes/admin");
  const app = express();

  // SECTION : Model
  const Product = require("./models/product");

  //SECTION : Tell Express use EJS Engine
  app.set("view engine", "ejs");
  app.set("views", "views");

  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(adminRoutes);

  // SECTION : Sequelize (sync)
  sequelize
    .sync()
    .then(result => {
      return Product.findByPk(1);
    })
    .catch(err => {
      console.log(err);
    });

  app.listen(3000);

Next create database connection in database.js inside util folder . My Database name is fruit with username & password root.

const Sequelize = require("sequelize");

const sequelize = new Sequelize("fruit", "root", "root", {
  dialect: "mysql",
  host: "localhost"
});

module.exports = sequelize;

Next the most important create controller name admin.js inside controller folder.Controller use for connect model and view and bring functionality

const Product = require("../models/product");

exports.getAddProduct = (req, res, next) => {
  res.render("add", {
        pageTitle: "Add Product",
        path: "/add",
        editing: false
   });};

      exports.postAddProduct = (req, res, next) => {
      const title = req.body.title;
      const imageUrl = req.body.imageUrl;
      const price = req.body.price;
      const stock = req.body.stock;
      const description = req.body.description;
      Product.create({
        title: title,
        price: price,
        stock: stock,
        imageUrl: imageUrl,
        description: description
      })
        .then(result => {
          // console.log(result);
          console.log("Created Product");
          res.redirect("/");
        })
        .catch(err => {
          console.log(err);
        });
    };

    exports.getEditProduct = (req, res, next) => {
      const editMode = req.query.edit;
      if (!editMode) {
        return res.redirect("/");
      }
      const prodId = req.params.productId;
      Product.findByPk(prodId)
        .then(product => {
          if (!product) {
            return res.redirect("/");
          }
          res.render("edit", {
            pageTitle: "Edit Product",
            path: "/edit",
            editing: editMode,
            product: product
          });
        })
        .catch(err => console.log(err));
    };

    exports.postEditProduct = (req, res, next) => {
      const prodId = req.body.productId;
      const updatedTitle = req.body.title;
      const updatedPrice = req.body.price;
      const updatedStock = req.body.stock;
      const updatedImageUrl = req.body.imageUrl;
      const updatedDesc = req.body.description;
      Product.findByPk(prodId)
        .then(product => {
          product.title = updatedTitle;
          product.price = updatedPrice;
          product.stock = updatedStock;
          product.description = updatedDesc;
          product.imageUrl = updatedImageUrl;
          return product.save();
        })
        .then(result => {
          console.log("UPDATED PRODUCT!");
          res.redirect("/");
        })
        .catch(err => console.log(err));
    };

    exports.getProducts = (req, res, next) => {
      Product.findAll()
        .then(products => {
          res.render("index", {
            prods: products,
            pageTitle: "Admin Products",
            path: "/"
          });
        })
        .catch(err => console.log(err));
    };

    exports.postDeleteProduct = (req, res, next) => {
      const prodId = req.body.productId;
      Product.findByPk(prodId)
        .then(product => {
          return product.destroy();
        })
        .then(result => {
          res.redirect("/");
        })
        .catch(err => console.log(err));
    };

Next create admin.js again inside routes folder and create routing & call from controller

const express = require("express");
const adminController = require("../controller/admin");
const router = express.Router();

router.get("/add", adminController.getAddProduct);
router.get("/", adminController.getProducts);
router.post("/add", adminController.postAddProduct);
router.get("/edit/:productId", adminController.getEditProduct);
router.post("/edit", adminController.postEditProduct);
router.post("/delete", adminController.postDeleteProduct);

module.exports = router;

Next , Create product.js inside models folder for manage database structure

    const Sequelize = require("sequelize");
    const sequelize = require("../util/database");
    const Product = sequelize.define("product", {

      id: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
      },
      title: {
        type: Sequelize.STRING
      },
      price: {
        type: Sequelize.DOUBLE,
        allowNull: false
      },
      imageUrl: {
        type: Sequelize.STRING,
        allowNull: false
      },
      stock: {
        type: Sequelize.INTEGER
      },
      description: {
        type: Sequelize.STRING,
        allowNull: false
      }
    });

    module.exports = Product;

Next we build the view. I will separate header and footer inside views/includes for use by 3 main file inside views which is index.ejs(for main page),add.ejs(for add product page),edit.ejs(for edit product).So this is good for modularity and clean code. Ok this is head.ejs inside views/includes:

<!DOCTYPE html>
    <html lang="en">
      <head>
        <title>Fruit App</title>
        <!-- Required meta tags -->
        <meta charset="utf-8" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />

        <!-- Bootstrap CSS -->
        <link
          rel="stylesheet"
          href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
          crossorigin="anonymous"
        />
      <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"></link>
      </head>
      <body>

        <!-- NAVBAR -->
      <nav class="navbar navbar-light bg-light">
        <a class="navbar-brand" href="/">
        <i class="fas fa-campground d-inline-block align-top mr-2 ml-2 mt-1 fa-lg"></i>
        Shop</a>
        <a class="navbar-brand ml-auto" href="/add"><i class="fas fa-plus"></i></i></a>
        <a class="navbar-brand ml-auto" href="https://www.instagram.com/faeshal_/" target="_blank"><i class="fab fa-instagram fa-lg"></i></a>
        <a class="navbar-brand" href="https://github.com/faeshal" target="_blank"><i class="fab fa-github fa-lg"></i></a>
      </nav>

and this is the end.ejs

<!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script
      src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
      integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
      integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
      integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
      crossorigin="anonymous"
    ></script>
  </body>
</html>

And the main view , index.ejs

<%-include("includes/head.ejs")%>
    <!-- SECTION: CONTENT -->
    <div class="container mb-2 mt-4">
      <h4 class="text-center mb-4">FRUITS</h4>
      <hr />
      <!-- SECTION : CARD -->
      <div class="row text-center">
        <% if (prods.length > 0) { %> <% for (let product of prods) { %>
        <div class="col-md-4 text-center ">
          <div class="card mb-4 mt-2 mr-4 ml-4 mx-auto" style="width: 17rem;">
            <h5 class="card-title text-center mt-2 mb-2"><%-product.title%></h5>
            <img
              class="card-img-top"
              src="<%-product.imageUrl%>"
              alt="Card image cap"
            />
            <div class="card-body text-center">
              <h5 class="card-title">$ <%-product.price%></h5>
              <h6 class="text-muted"><%-product.stock%> Stock</h6>
              <p class="card-text">
                <%-product.description%>
              </p>

              <form id="myForm" method="POST" action="/delete">
                <a
                  href="/edit/<%= product.id %>?edit=true"
                  class="btn btn-warning mr-3"

                  >Update</a
                >
                <input type="hidden" value="<%= product.id %>" name="productId" />
                <button
                  class="btn btn-danger"
                  onclick="return confirm('Are You Sure?');"
                >
                  Delete
                </button>
              </form>
            </div>
          </div>
        </div>
        <% } %>

        <!-- END CARD -->
        <% } else { %>
        <h6 class="text-center">No Product</h6>
        <% } %>
      </div>
    </div>
    <!--  -->

    <%-include("includes/end.ejs")%>

This is Add.ejs

  <%-include("includes/head.ejs")%>
    <!-- SECTION:CONTENT -->
    <div class="container" class="mt-4 ml-2 mr-2">
      <h4 class="text-center mt-4">ADD PRODUCTS</h4>
      <hr />
      <div class="row">
        <div class="col-sm-10 mx-auto">
          <form action="/add" method="POST">
            <div class="form-group mt-4">
              <input
                type="text"
                name="title"
                class="form-control"
                id="title"
                aria-describedby="title"
                placeholder="Name"
              />
            </div>
            <div class="form-group">
              <input
                type="text"
                class="form-control"
                name="imageUrl"
                id="imageUrl"
                placeholder="Image Url"
              />
            </div>
            <div class="form-group">
              <input
                type="number"
                class="form-control"
                name="price"
                id="price"
                placeholder="Price"
              />
            </div>
            <div class="form-group">
              <input
                type="number"
                class="form-control"
                name="stock"
                id="stock"
                placeholder="Stock"
              />
            </div>
            <div class="form-group">
              <textarea
                class="form-control"
                name="description"
                id="description"
                rows="3"
                ,
                placeholder="Description"
              ></textarea>
            </div>
            <div class="text-center">
              <button type="submit" class="btn btn-outline-success btn-lg">
                Submit
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!--  -->
    <%-include("includes/end.ejs")%>

This is Edit.ejs

  <%-include("includes/head.ejs")%> <
    <!-- SECTION:CONTENT -->
    <div class="container" class="mt-4 ml-2 mr-2">
      <h4 class="text-center mt-4">EDIT PRODUCTS</h4>
      <hr>
      <div class="row">
          <div class="col-sm-10 mx-auto">
      <form action="/edit" method="POST">
        <input type="hidden" value="<%= product.id %>" name="productId" />
        <div class="form-group mt-4">
          <input
            type="text"
            class="form-control"
            id="title"
            name="title"
            value="<%= product.title %>"
            aria-describedby="emailHelp"
          />
        </div>
        <div class="form-group">
          <input
            type="text"
            class="form-control"
            id="imageUrl"
            name="imageUrl"
            value="<%= product.imageUrl %>"
            aria-describedby="emailHelp"
          />
        </div>
        <div class="form-group">
          <input
            type="number"
            class="form-control"
            id="price"
            name="price"
            value="<%= product.price %>"
            aria-describedby="emailHelp"
          />
        </div>
        <div class="form-group">
          <input
            type="text"
            class="form-control"
            id="stock"
            name="stock"
            value="<%= product.stock %>"
            aria-describedby="emailHelp"
          />
        </div>
        <div class="form-group">
          <textarea
            class="form-control"
            name="description"
            id="description"
            rows="3"
            placeholder="Description"
          >
    <%= product.description %></textarea
          >
        </div>
        <div class="text-center">
          <button
            id="update"
            class="btn btn-outline-warning btn-lg"
            onclick="Update()"
            value="UPDATE"
          >
            UPDATE
          </button>
        </div>
    </div>
    </div>
    </div>

    <!--  -->
    <%-include("includes/end.ejs")%>
Result

Anyway you can create your own design for example the card and navbar with your style for sure, dont forget to npm start  for start the server . This is my result:

Let’s Try add Functionality :

This is Edit Functionality

And the last Delete functionality with destroy method ini Express

Last Word

Hope you understand how Nodejs handle the request , work flow with express and bring the data with sequelize. Dont forget to check documentation for details as always link down below.