# CRUD MongoDB

Realizaremos las operaciones de leer, crear, editar y eliminar documentos utilizando MongoDB y Express.

# Leer

En la sección anterior conocimos como conectarnos a mongoDB y leer documentos, por ende utilizaremos el mismo proyecto, si gustas lo puedes revisar aquí:

# bodyParser

Tenemos que instalar para utilizar x-www-form-urlencoded

https://www.npmjs.com/package/body-parser

npm i body-parser

https://www.npmjs.com/package/body-parser#expressconnect-top-level-generic

const express = require('express');
const bodyParser = require('body-parser')
const app = express();


// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())

# Crear

Ruta

router.get('/crear', (req, res) => {
    res.render('crear')
})

Formulario

<%- include("template/cabecera", {tituloWeb: 'Mascotas'}) %>

  <div class="container">

    <h1>Crear nueva mascota</h1>
    
    <form action="/mascotas" class="my-2" method="POST">
    
        <input 
            type="text"
            placeholder="Ingrese Nombre"
            class="form-control my-2"
            name="nombre"
        >
    
        <input 
            type="text"
            placeholder="Ingrese Descripción"
            class="form-control my-2"
            name="descripcion"
        >
    
        <button
            type="submit"
            class="btn btn-dark btn-block"
        >
            Agregar
        </button>
    
    </form>

  </div>

    
<%- include("template/footer") %>

POST

router.post('/', async (req, res) => {
    const body = req.body
    console.log(body)
})

GUARDAR Método #1: https://mongoosejs.com/docs/models.html

router.post('/', async (req, res) => {
    const body = req.body
    console.log(body)
    try {
        const mascotaDB = new Mascota(body)
        await mascotaDB.save()
        res.redirect('/mascotas')
    } catch (error) {
        console.log('error', error)
    }
})

GUARDAR Método #2: https://mongoosejs.com/docs/api.html#model_Model.create

router.post('/', async (req, res) => {
    const body = req.body
    console.log(body)
    try {
        await Mascota.create(body)
        res.redirect('/mascotas')
    } catch (error) {
        console.log('error', error)
    }
})

# Get único documento

Creamos el botón para viajar a la ruta detalle:

<tr>
  <th scope="row"><%= mascota.id %></th>
  <td><%= mascota.nombre %> </td>
  <td><%= mascota.descripcion %></td>
  <td>
    <a
      class="btn btn-warning btn-sm"
      href="mascotas/<%= mascota.id %>"
    >
      Editar
    </a>
  </td>
</tr>

Creamos la ruta con su respectivo render:

router.get('/:id', async(req, res) => {
    const id = req.params.id
    try {
        const mascotaDB = await Mascota.findOne({ _id: id })
        console.log(mascotaDB)
        res.render('detalle', {
            mascota: mascotaDB,
            error: false
        })
    } catch (error) {
        console.log('erroooooooooorrr', error)
        res.render('detalle', {
            error: true,
            mensaje: 'No se encuentra el documento...'
        })
    }
})

Pintamos el detalle del documento:

<%- include("template/cabecera", {tituloWeb: 'Mascotas'}) %>

  <div class="container">
    
    <h1>Detalle Mascota</h1>
  
    <% if (error) { %>
        <%= mensaje %> 
        <a 
            href="/mascotas"
            class="btn btn-dark btn-block my-2"
        >
            Volver
        </a>
    <% } %>

    <% if (!error) { %>
        <table class="table">
            <thead>
                <tr>
                <th scope="col">#</th>
                <th scope="col">Nombre</th>
                <th scope="col">Descripción</th>
                <th scope="col">Acción</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th scope="row"><%= mascota.id %></th>
                    <td><%= mascota.nombre %> </td>
                    <td><%= mascota.descripcion %></td>
                    <td>
                        <button
                        class="btn btn-danger btn-sm"
                        data-id="<%= mascota.id %>"
                        >
                        Eliminar
                        </button>
                    </td>
                </tr>
            </tbody>
        </table>
    <% } %>
     
  </div>
    
<%- include("template/footer") %>

# Delete documento

<button
  class="btn btn-danger btn-sm"
  data-id="<%= mascota.id %>"
>
  Eliminar
</button>

Creamos la lógica del botón eliminar:

<script>
// onclick vs addEventListener
// https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick#:~:text=Essentially%20onclick%20is%20a%20HTML,(using%20this%20for%20example).

const btnEliminar = document.querySelector('.btn-danger')
  btnEliminar.addEventListener('click', async() => {
    console.log(btnEliminar.dataset.id)  
    try {
        // https://developer.mozilla.org/es/docs/Web/API/HTMLElement/dataset
        const data = await fetch(`/mascotas/${btnEliminar.dataset.id}`, {
          method: 'delete'
        })
        const res = await data.json()
        console.log(res)
        if(res.estado){
            window.location.href = '/mascotas'
        }else{
            console.log(res)
        }
    } catch (error) {
        console.log(error)
    }
  })

</script>

Creamos la ruta correspondiente:

router.delete('/:id', async (req, res) => {
    const id = req.params.id;
    console.log('id desde backend', id)
    try {

        const mascotaDB = await Mascota.findByIdAndDelete({ _id: id });
        console.log(mascotaDB)

        // https://stackoverflow.com/questions/27202075/expressjs-res-redirect-not-working-as-expected
        // res.redirect('/mascotas')
        if (!mascotaDB) {
            res.json({
                estado: false,
                mensaje: 'No se puede eliminar'
            })
        } else {
            res.json({
                estado: true,
                mensaje: 'eliminado!'
            })
        }
        
    } catch (error) {
        console.log(error)
    }
})

# Editar documento

Detalle.ejs

<% if (!error) { %>
    <form id="editar" data-id="<%= mascota.id %>">
        <input 
            type="text"
            value="<%= mascota.nombre %>"
            class="form-control my-2"
            name="nombre"
            id="nombreInput"
        >
        <input 
            type="text"
            value="<%= mascota.descripcion %>"
            class="form-control my-2"
            name="descripcion"
            id="descripcionInput"
        >
        <button
            class="btn btn-warning btn-sm"
            type="submit"
        >
            Editar
        </button>
    </form>
    <hr>
    <button
        class="btn btn-danger btn-sm"
        data-id="<%= mascota.id %>"
    >
        Eliminar
    </button>
<% } %>
const formEditar = document.querySelector('#editar');

formEditar.addEventListener('submit', async(e) => {
    e.preventDefault()
    // Alternativa #1 (capturar input)
    const nombre = formEditar.elements['nombre'].value
    // Alternativa #2 (capturar input)
    const descripcion = document.querySelector('#descripcionInput').value
    const id = formEditar.dataset.id 

    const data = await fetch(`/mascotas/${id}`, {
        method: 'PUT',
        headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: JSON.stringify({nombre, descripcion})
    })

    const res = await data.json()

    if(res.estado){
        window.location.href = '/mascotas'
    }else{
        console.log(res)
    }

})
router.put('/:id', async (req, res) => {
    const id = req.params.id;
    const body = req.body;

    console.log(id)
    console.log('body', body)

    try {
        const mascotaDB = await Mascota.findByIdAndUpdate(
            id, body, { useFindAndModify: false }
        )
        console.log(mascotaDB)
        res.json({
            estado: true,
            mensaje: 'Mascota editada'
        })
    } catch (error) {
        console.log(error)
        res.json({
            estado: false,
            mensaje: 'Mascota falla'
        })
    }
})