5-Express--Curso de Node.js#05 Introducción a Express.js

Express: Dominando Servidores Web con Node.js y Express

  5- EXPRESS

           |

          V

6-MIDDLEWARE


mi-app/

├app.js

└── package.json

Comando:

bash
npm init -y

Instalando dependencias.

bash
npm install express

El error principal está en la etiqueta <a>: escribiste hreft en lugar de href. Además, hay un error en el cierre de la etiqueta <style>.

Aquí está el código corregido:

javascript
const express = require('express');
const app = express();
const port = 3000;

app.use(express.urlencoded({extended:true}));

//Arreglo de productos
let productos = [
    {id:1, nombre:'Coca-cola', precio:100},
    {id:2, nombre:'pepsi', precio:90}
];

app.get('/', (req,res)=>{
    let lista ='';
    for(let i=0; i< productos.length; i++){
        lista += `
        <li>
        <strong>${productos[i].nombre}</strong> - $${productos[i].precio}
        (<a href="/productos/${productos[i].id}">Ver detalles</a>)
        </li>
        `;
    }

    res.send(`
        <!DOCTYPE html>
        <html>
        <head>
            <title>Productos</title>
            <style>body {font-family: Arial; margin: 30px;} li { margin: 10px 0;}</style>
        </head>
        <body>
            <h1> Lista de productos</h1>
            <ul>${lista}</ul>
            <hr>
        </body>
        </html>`);
});

app.listen(port, () => console.log(`Servidor escuchando en http://localhost:${port}`));

L

Código completo (app.js)

javascript
const express = require('express');
const app = express();
const PORT = 3000;

// Para leer datos de formularios
app.use(express.urlencoded({ extended: true }));

// Arreglo de productos
let productos = [
  { id: 1, nombre: 'Laptop', precio: 1000 },
  { id: 2, nombre: 'Mouse', precio: 25 },
  { id: 3, nombre: 'Teclado', precio: 50 }
];

// ========== MÉTODO 1: Ver todos los productos (página principal) ==========
app.get('/', (req, res) => {
  let lista = '';
  for (let i = 0; i < productos.length; i++) {
    lista += `
      <li>
        <strong>${productos[i].nombre}</strong> - $${productos[i].precio}
        (<a href="/productos/${productos[i].id}">Ver detalles</a>)
      </li>
    `;
  }

  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>Productos</title>
      <style>body { font-family: Arial; margin: 30px; } li { margin: 10px 0; }</style>
    </head>
    <body>
      <h1>📦 Lista de productos</h1>
      <ul>${lista}</ul>

      <hr>
      <h2>➕ Agregar producto</h2>
      <form action="/productos" method="POST">
        <input type="text" name="nombre" placeholder="Nombre" required>
        <input type="number" step="1" name="precio" placeholder="Precio" required>
        <button type="submit">Crear</button>
      </form>
    </body>
    </html>
  `);
});

// ========== MÉTODO 2: Ver un producto específico por ID (página de detalle) ==========
app.get('/productos/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const producto = productos.find(p => p.id === id);

  if (!producto) {
    return res.send('<h1>404 - Producto no encontrado</h1><a href="/">Volver</a>');
  }

  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>${producto.nombre}</title>
      <style>body { font-family: Arial; margin: 30px; }</style>
    </head>
    <body>
      <h1>📄 Detalle del producto</h1>
      <p><strong>ID:</strong> ${producto.id}</p>
      <p><strong>Nombre:</strong> ${producto.nombre}</p>
      <p><strong>Precio:</strong> $${producto.precio}</p>
      <a href="/">← Volver al listado</a>
    </body>
    </html>
  `);
});

// ========== MÉTODO 3: Crear un nuevo producto (recibe POST y redirige) ==========
app.post('/productos', (req, res) => {
  const { nombre, precio } = req.body;
  if (!nombre || !precio) {
    return res.send('<h1>Error: faltan datos</h1><a href="/">Volver</a>');
  }

  // Calcular nuevo ID
  const nuevoId = productos.length > 0 ? Math.max(...productos.map(p => p.id)) + 1 : 1;
  const nuevoProducto = { id: nuevoId, nombre, precio: parseFloat(precio) };
  productos.push(nuevoProducto);

  // Redirige a la página principal (MÉTODO 1)
  res.redirect('/');
});

// Iniciar servidor
app.listen(PORT, () => console.log(`Servidor en http://localhost:${PORT}`));

Paso 2: Ejecutar el archivo

En tu terminal (ubicado en la carpeta del proyecto), ejecuta:

bash
node app.js

✅ ¿Qué hace?

  • Método 1 (GET /) → Muestra todos los productos en una lista HTML. Cada producto tiene un enlace a su detalle.

  • Método 2 (GET /productos/:id) → Muestra un solo producto en una página HTML con sus datos.

  • Método 3 (POST /productos) → Recibe los datos del formulario, crea el producto y redirige a la lista actualizada.

No hay rutas JSON, todo es HTML puro desde el servidor.


▶️ Cómo usarlo en clase

  1. Guardar como app.js

  2. Ejecutar node app.js

  3. Abrir http://localhost:3000

  4. Probar:

    • Ver todos los productos.

    • Hacer clic en "Ver detalles" de uno.

    • Usar el formulario para agregar un producto nuevo.

¡Ideal para que los alumnos entiendan cómo generar HTML dinámico desde un arreglo, sin necesidad de JavaScript en el frontend!

Cómo funciona res.send()

res.send() es un método que envía una respuesta HTTP al navegador. Puede enviar:

  • HTML (texto con etiquetas)

  • JSON (objetos)

  • Texto plano

javascript
// Ejemplos de res.send():
res.send('<h1>Hola</h1>');        // Envía HTML
res.send({ nombre: 'Juan' });     // Envía JSON
res.send('Texto normal');         // Envía texto

🔍 MÉTODO 1: GET '/' - Ver todos los productos

javascript
app.get('/', (req, res) => {
  // PASO 1: Crear una variable string vacía
  let lista = '';
  
  // PASO 2: Recorrer el arreglo de productos
  for (let i = 0; i < productos.length; i++) {
    // PASO 3: Por CADA producto, agregar HTML a 'lista'
    lista += `
      <li>
        <strong>${productos[i].nombre}</strong> - $${productos[i].precio}
        (<a href="/productos/${productos[i].id}">Ver detalles</a>)
      </li>
    `;
  }
  
  // PASO 4: Enviar TODO el HTML con los datos inyectados
  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>Productos</title>
      <style>body { font-family: Arial; margin: 30px; } li { margin: 10px 0; }</style>
    </head>
    <body>
      <h1>📦 Lista de productos</h1>
      <ul>${lista}</ul>  <!-- AQUÍ se inyecta la variable 'lista' -->

      <hr>
      <h2>➕ Agregar producto</h2>
      <form action="/productos" method="POST">
        <input type="text" name="nombre" placeholder="Nombre" required>
        <input type="number" step="1" name="precio" placeholder="Precio" required>
        <button type="submit">Crear</button>
      </form>
    </body>
    </html>
  `);
});

📌 Cómo se inyecta la información:

text
productos = [
  { id: 1, nombre: 'Laptop', precio: 1000 },
  { id: 2, nombre: 'Mouse', precio: 25 }
]

↓ El for convierte esto en ↓

lista = `
  <li><strong>Laptop</strong> - $1000 (<a href="/productos/1">Ver detalles</a>)</li>
  <li><strong>Mouse</strong> - $25 (<a href="/productos/2">Ver detalles</a>)</li>
`

↓ Se inyecta en ${lista} dentro del HTML ↓

<ul>${lista}</ul> → <ul><li><strong>Laptop</strong> - $1000...</li></ul>

🔍 MÉTODO 2: GET '/productos/:id' - Ver un producto

javascript
app.get('/productos/:id', (req, res) => {
  // PASO 1: Extraer el ID de la URL (ej: /productos/2 → id=2)
  const id = parseInt(req.params.id);
  
  // PASO 2: Buscar el producto en el arreglo
  const producto = productos.find(p => p.id === id);
  
  // PASO 3: Si NO existe, enviar error 404
  if (!producto) {
    return res.send('<h1>404 - Producto no encontrado</h1><a href="/">Volver</a>');
  }
  
  // PASO 4: Si existe, enviar HTML con los datos del producto
  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>${producto.nombre}</title>
      <style>body { font-family: Arial; margin: 30px; }</style>
    </head>
    <body>
      <h1>📄 Detalle del producto</h1>
      <p><strong>ID:</strong> ${producto.id}</p>
      <p><strong>Nombre:</strong> ${producto.nombre}</p>
      <p><strong>Precio:</strong> $${producto.precio}</p>
      <a href="/">← Volver al listado</a>
    </body>
    </html>
  `);
});

📌 Cómo funciona el :id (parámetro de ruta):

text
URL del navegador: http://localhost:3000/productos/2

Express interpreta:
req.params.id = "2" (string)
parseInt("2") = 2 (número)

productos.find(p => p.id === 2) → encuentra { id: 2, nombre: 'Mouse', precio: 25 }

↓ Se inyecta cada propiedad en ${} ↓

<title>${producto.nombre}</title> → <title>Mouse</title>
<p>Precio: $${producto.precio}</p> → <p>Precio: $25</p>

🔍 MÉTODO 3: POST '/productos' - Crear producto

javascript
app.post('/productos', (req, res) => {
  // PASO 1: Extraer datos del formulario (vienen en req.body)
  const { nombre, precio } = req.body;
  
  // PASO 2: Validar que llegaron datos
  if (!nombre || !precio) {
    return res.send('<h1>Error: faltan datos</h1><a href="/">Volver</a>');
  }
  
  // PASO 3: Calcular el nuevo ID
  const nuevoId = productos.length > 0 
    ? Math.max(...productos.map(p => p.id)) + 1 
    : 1;
  
  // PASO 4: Crear el objeto producto
  const nuevoProducto = { 
    id: nuevoId, 
    nombre,           // viene del formulario
    precio: parseFloat(precio)  // viene del formulario
  };
  
  // PASO 5: Agregar al arreglo
  productos.push(nuevoProducto);
  
  // PASO 6: Redirigir a la página principal
  res.redirect('/');
});

📌 Cómo fluyen los datos del formulario:

text
1. Usuario llena formulario:
   [Input nombre] = "Monitor"
   [Input precio] = 300

2. Navegador hace POST a /productos con:
   body: { nombre: "Monitor", precio: "300" }

3. Express procesa con middleware:
   app.use(express.urlencoded({ extended: true }))
   Convierte los datos a un objeto JavaScript

4. req.body contiene:
   { nombre: "Monitor", precio: "300" }

5. Destructuring:
   const { nombre, precio } = req.body;
   → nombre = "Monitor", precio = "300"

6. Se crea nuevo producto:
   nuevoProducto = {
     id: 4,
     nombre: "Monitor",
     precio: 300 (convertido a número)
   }

7. Se agrega al arreglo productos
   productos = [Laptop, Mouse, Teclado, Monitor]

8. res.redirect('/') hace que el navegador vuelva a GET /
   ¡Ahora la lista muestra el nuevo producto!

🎯 Resumen visual de inyección de datos:

text
DATOS ORIGINALES          ↓ INYECCIÓN          ↓ RESULTADO FINAL
──────────────────────────────────────────────────────────────
productos[0].nombre       ${productos[i].nombre}    "Laptop"
= "Laptop"                en el HTML                 
                                           
                         <li><strong>Laptop</strong></li>

──────────────────────────────────────────────────────────────
req.params.id             ${producto.id}            "2"
= "2"                     en el HTML
                                           
                         <p>ID: 2</p>

──────────────────────────────────────────────────────────────
req.body.nombre          ${nuevoProducto.nombre}   "Monitor"
= "Monitor"              en el objeto
                                           
                         nuevoProducto = { nombre: "Monitor" }

💡 Conceptos clave:

ConceptoExplicación
Template literalsLas comillas ` permiten usar ${variable} para inyectar valores |
req.paramsCaptura parámetros de la URL como :id
req.bodyCaptura datos enviados por formularios (POST)
res.send()Envía la respuesta HTML al navegador
res.redirect()Redirige a otra ruta después de procesar datos







Comentarios

Entradas más populares de este blog

Cómo Iniciar un Proyecto Node.js

8-Template Engines