Como Crear un CRUD con Node JS (19.4.2) y Bootstrap 5 – Parte 3

Demo

En la parte anterior o parte 2 de este tutorial configuramos un elemento muy importante para nuestro sistema CRUD, me refiero a la base de datos, si nuestro proyecto no cuenta con una base de datos, no tendria ni pie ni cabeza, si bien podemos crear proyectos con Node JS de otros tipos, para al menos uno que realice operaciones CRUD (Create, Read, Update y Delete), necesita de una base de datos para poder ejecutarlas. En esta parte 3 continuamos con el tutorial Como Crear un CRUD con Node JS (19.4.2) y Bootstrap 5, vamos con ello.

Partes


Antes de continuar con este Post, te invito a leer los siguientes artículos:

Asimismo, te invito a escuchar el Podcast: “No Encuentro Empleo Por Mi Edad ¿ Que Puedo Hacer ?“Ventajas y Desventajas de Usar 2 o Más Monitores Para un Desarrollador” (Anchor Podcast): 

Spotify: Sound Cloud: Apple Podcasts Anchor Podcasts

Bien ahora continuemos con el Post: Como Como Crear un CRUD con Node JS (19.4.2) y Bootstrap 5 – Parte 3.

Conexión a la Base de Datos

Voy a conectar Node JS con la base de datos y la tabla productos que creamos en la Parte 2 de este tutorial. Para esto creo un directorio con el nombre config y dentro de el creo un archivo con el nombre db.js:

/crud-nodejs19-bootstrap5  
├── /config 
    ├── db.js // Creo y abro este archivo 
├── /node_modules 
├── app.js 
├── package.json  
├── package-lock.json

Abro el archivo db.js y dentro de el agrego lo siguiente (He colocado comentarios en el código para explicar que hacen ciertas partes del código):

'use strict';
const mysql = require('mysql');

// Conexión a la base de datos 
const con = mysql.createConnection({
  host     : 'localhost', // Host
  user     : 'root',      // Usuario 
  password : '',          // Password  
  database : 'crud-nodejs19-bootstrap5' // Base de datos 
});

// Realizamos la conexión 
con.connect(function(err) {
  if (err) throw err;
  console.log("Conectado a la Base de Datos !");
}); 

// Exportamos este módulo 
module.exports = con;

En el código anterior hago un console.log(“Conectado a la Base de Datos !”), con un mensaje para mostrar en la consola, confirmando que la conexión se ha realizado correctamente.

Controlador

Para manejar los datos entre la vista y el modelo (el modelo lo crearemos más adelante), necesitaré de un controlador. Para esto creo un directorio con el nombre controllers y dentro de el creo un archivo llamado productos.js:

/crud-nodejs19-bootstrap5  
├── /config 
├── /controllers 
    ├── productos.js // Creo y abro este archivo 
├── /node_modules 
├── app.js 
├── package.json  
├── package-lock.json

Abro el archivo productos.js y dentro de el agrego 5 funciones para las tareas del sistema CRUD, estas son Crear, Leer, Actualizar, Eliminar y una que seria listar todos los registros en la vista principal:

'use strict';
const Producto = require('../models/productos');

// Listar todos los productos en la vista principal  
exports.findAll = function(req, res) {
  Producto.findAll(function(err, producto) {    
    if (err)
    res.send(err);
    console.log('Datos:', producto);
    res.status(200).send(producto)
  });
};

// Crear un producto 
exports.create = function(req, res) { 
  // Mostramos un mensaje cuando los campos esten vacios 
  if(req.body.constructor === Object && Object.keys(req.body).length === 0){
    res.status(400).send({ error:true, message: 'Por favor proporciona todos los campos requeridos !' });
  }else{

    // Creo un objeto para añadir el nombre de la imagen 
    const producto = {
      nombre: req.body.nombre,
      precio: req.body.precio,
      stock: req.body.stock,
      img: req.file.filename // Nombre de la imagen 
    }; 
  
    const nuevo_producto = new Producto(producto);
    
    Producto.create(nuevo_producto, function(err, producto) {
      if (err)
      res.send(err);
      req.flash('message', 'Producto Creado Correctamente !');
      res.redirect('/');
    });
  }
};

// Leer un producto  
exports.findById = function(req, res) {
  Producto.findById(req.params.id, function(err, producto) {
    if (err)
    res.send(err);
    res.json(producto);
  });
}; 

// Actualizar un producto 
exports.update = function(req, res) {

  if(req.file != null){
    console.log("No esta vacio");

    // Creo un objeto para añadir el nuevo nombre de la imagen 
    const producto = {
      nombre: req.body.nombre,
      precio: req.body.precio,
      stock: req.body.stock,
      img: req.file.filename // Nuevo nombre de la imagen 
    }; 

    Producto.update(req.params.id, new Producto(producto), function(err, producto) {      
      req.flash('message', 'Producto Actualizado Correctamente !');
      res.redirect('/');
    });

  }else{

    console.log("Si esta vacio");

    Producto.findById(req.params.id, function(err, producto) {    
      const key = "img";
      const value = producto[0].img;

      // Creo un objeto para mantener el nombre actual de la imagen 
      const aproducto = {
        nombre: req.body.nombre,
        precio: req.body.precio,
        stock: req.body.stock,
        [key]: value, // Nombre actual de la imagen 
      }; 

      Producto.update(req.params.id, new Producto(aproducto), function(err, aproducto) {      
        req.flash('message', 'Producto Actualizado Correctamente !');
        res.redirect('/');
      });

    });     

  }    
  
};

// Eliminar un producto 
exports.delete = function(req, res) {
  Producto.delete( req.params.id, function(err, producto) {
    req.flash('message', 'Producto Eliminado Correctamente !');
    res.redirect('/');
  });
};

En el código anterior la primera función para Listar todos los productos en la vista principal, nos permitirá mostrar todos los productos en una tabla HTML que la crearé con Bootstrap más adelante.

Modelo

Dentro de nuestro modelo vamos a ejecutar las consultas o queries a nuestra base de datos, especificamente a la tabla productos. Creo un directorio con el nombre models y dentro de el creo un archivo con el nombre productos.js:

/crud-nodejs19-bootstrap5  
├── /config 
├── /controllers  
├── /models 
    ├── productos.js // Creo y abro este archivo 
├── /node_modules 
├── app.js 
├── package.json  
├── package-lock.json

Abro el archivo productos.js y le agrego lo siguiente:

'use strict';
var conexion = require('../config/db');

// Campos del producto (Objeto) 
var Producto = function(producto){
  this.nombre     = producto.nombre;
  this.precio     = producto.precio;
  this.stock      = producto.stock;
  this.img        = producto.img;
  this.updated_at = new Date();
};

// Crear un Producto 
Producto.create = function (newEmp, result) {
  conexion.query("INSERT INTO productos set ?", newEmp, function (err, res) {
    if(err) {
      console.log("error: ", err);
      result(err, null);
    }
    else{
      console.log(res.insertId);
      result(null, res.insertId);
    }
  });
};

// Leer un Producto por su ID 
Producto.findById = function (id, result) {
  conexion.query("Select * from productos where id = ? ", id, function (err, res) {
    if(err) {
      console.log("error: ", err);
      result(err, null);
    }
    else{
      result(null, res);
    }
  });
};

// Listar todos los productos en la Vista Principal 
Producto.findAll = function (result) {
  conexion.query("Select * from productos", function (err, res) {
    if(err) {
      console.log("error: ", err);
      result(null, err);
    }
    else{
      result(null, res);
    }
  });
}; 

// Actualizar un Producto por su ID 
Producto.update = function(id, producto, result){
  conexion.query("UPDATE productos SET nombre=?,precio=?,stock=?,img=?,updated_at=? WHERE id = ?", [producto.nombre,producto.precio,producto.stock,producto.img,producto.updated_at, id], function (err, res) {
    if(err) {
      console.log("error: ", err);
      result(null, err);
    }else{
      result(null, res);
    }
  });
}; 

// Eliminar un Producto por su ID 
Producto.delete = function(id, result){
  conexion.query("DELETE FROM productos WHERE id = ?", [id], function (err, res) {
    if(err) {
      console.log("error: ", err);
      result(null, err);
    }
    else{
      result(null, res);
    }
  });
};
module.exports = Producto;

En el código anterior, cada función realizar una tarea CRUD especifica y en cada una de ellas hacemos consultas SQL a la base de datos, especificamente a la tabla productos.

Servidor

En la Parte 1 de este tutorial, creamos un servidor sencillo con Node JS, para verificar si el proyecto se había creado correctamente. Esto lo hicimos dentro del archivo app.js

Voy a realizar modificaciones en el archivo app.js para que la base de datos, el controlador, el modelo y las rutas (Las rutas las crearé más adelante), trabajen de manera adecuada. Abro el archivo app.js:

/crud-nodejs19-bootstrap5  
├── /config 
├── /controllers  
├── /models 
├── /node_modules 
├── app.js // Abro este archivo 
├── package.json  
├── package-lock.json

Elimino lo que habia en el archivo app.js y agrego lo siguiente:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const path = require("path") // Path 

const session = require('express-session');
app.use(session({secret: 'mySecret', resave: false, saveUninitialized: false})); 

const flash = require('express-flash'); 
app.use(flash());

// EJS template engine 
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "/views"));

// Puerto 
const port = process.env.PORT || 3000;

// Peticiones de tipo application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))

// Peticiones de tipo application/json
app.use(bodyParser.json())

// Ruta Productos 
const ruta_productos = require('./routes/productos');
const con = require('./config/db');

// Usamos un Middleware 
app.use('/api/v1/productos', ruta_productos)

// Directorio de las imágenes 
app.use("/uploads",express.static(path.join(__dirname, "uploads")))

// Escuchamos las peticiones en el puerto establecido 
app.listen(port, () => {
  console.log(`La Aplicación está funcionando en el puerto ${port}`);
});

En el código anterior, puedes ver que agregue la ruta para los productos, estas rutas las crearé más adelante.

Entonces ya  tenemos hecha la conexión a la base de datos, creamos nuestro controlador, asimismo el modelo para las consultas a la tabla productos y realice modificaciones en el archivo del servidor app.js

Ten Paciencia, lo que quiero es que conozcas bien como se crea este proyecto y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje. 

Nota (s)

  • En la siguiente parte vamos a crear las rutas y las vistas del sistema CRUD.
  • No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo. 

Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.