Guía Completa de Formularios con Node.js, Express y EJS

Configuración Inicial del Proyecto


1Crear Estructura del Proyecto
bash
# Crear directorio del proyecto
mkdir formulario-nodejs-ejs
cd formulario-nodejs-ejs
2Inicializar proyecto
bash
npm init -y
2Instalar dependencias
bash
npm install express ejs body-parser
2Estructura de Directorios
bash
formulario-nodejs-ejs/
│
├── public/
│   └── css/
│       └── styles.css
│
├── views/
│   ├── index.ejs
│   ├── formulario.ejs
│   └── resultado.ejs
│
├── server.js
└── package.json

Configuración del Servidor Express


Archivo server.js

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

const app = express();
const PORT = process.env.PORT || 3000;

// Configurar EJS como motor de plantillas
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// Middleware para archivos estáticos
app.use(express.static(path.join(__dirname, 'public')));

// Middleware para parsear datos de formularios
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// Rutas
app.get('/', (req, res) => {
res.render('index', { titulo: 'Página Principal' });
});

// Ruta para mostrar formulario
app.get('/formulario', (req, res) => {
res.render('formulario', { 
  titulo: 'Formulario de Registro',
  error: null 
});
});

// Ruta para procesar formulario
app.post('/enviar-formulario', (req, res) => {
const { nombre, email, mensaje } = req.body;

// Validación básica
const errores = [];
if (!nombre) errores.push('El nombre es requerido');
if (!email) errores.push('El email es requerido');

if (errores.length > 0) {
  return res.render('formulario', {
    titulo: 'Error en el Formulario',
    error: errores,
    datosAnteriores: req.body
  });
}

// Procesar datos
res.render('resultado', { 
  titulo: 'Resultado del Formulario',
  nombre, 
  email, 
  mensaje 
});
});

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

Plantillas EJS


views/index.ejs

ejs
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><%= titulo %></title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="container">
  <h1>Bienvenido</h1>
  <nav>
    <a href="/formulario" class="btn">Ir al Formulario</a>
  </nav>
</div>
</body>
</html>

views/formulario.ejs

ejs
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><%= titulo %></title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="container">
  <h1><%= titulo %></h1>
  
  <% if (locals.error) { %>
    <div class="alert error">
      <% error.forEach(function(err) { %>
        <p><%= err %></p>
      <% }); %>
    </div>
  <% } %>

  <form action="/enviar-formulario" method="POST">
    <div class="form-group">
      <label for="nombre">Nombre:</label>
      <input 
        type="text" 
        id="nombre" 
        name="nombre" 
        value="<%= locals.datosAnteriores && datosAnteriores.nombre || '' %>"
        required
      >
    </div>

    <div class="form-group">
      <label for="email">Email:</label>
      <input 
        type="email" 
        id="email" 
        name="email" 
        value="<%= locals.datosAnteriores && datosAnteriores.email || '' %>"
        required
      >
    </div>

    <div class="form-group">
      <label for="mensaje">Mensaje:</label>
      <textarea 
        id="mensaje" 
        name="mensaje" 
        rows="4"
      ><%= locals.datosAnteriores && datosAnteriores.mensaje || '' %></textarea>
    </div>

    <button type="submit" class="btn">Enviar</button>
  </form>
</div>
</body>
</html>

views/resultado.ejs

ejs
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><%= titulo %></title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="container">
  <h1>Resultado del Formulario</h1>
  
  <div class="resultado">
    <p><strong>Nombre:</strong> <%= nombre %></p>
    <p><strong>Email:</strong> <%= email %></p>
    <% if (mensaje) { %>
      <p><strong>Mensaje:</strong> <%= mensaje %></p>
    <% } %>
  </div>

  <a href="/formulario" class="btn">Volver al Formulario</a>
</div>
</body>
</html>

public/css/styles.css

css
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}

.container {
width: 80%;
max-width: 600px;
margin: 2rem auto;
background-color: white;
padding: 2rem;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.form-group {
margin-bottom: 1rem;
}

label {
display: block;
margin-bottom: 0.5rem;
}

input, textarea {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}

.btn {
display: inline-block;
background-color: #007bff;
color: white;
padding: 0.5rem 1rem;
text-decoration: none;
border: none;
border-radius: 4px;
cursor: pointer;
}

.alert.error {
background-color: #f8d7da;
color: #721c24;
padding: 0.75rem;
margin-bottom: 1rem;
border-radius: 4px;
}

Configuración del package.json


json
{
"name": "formulario-nodejs-ejs",
"version": "1.0.0",
"scripts": {
  "start": "node server.js",
  "dev": "nodemon server.js"
},
"dependencies": {
  "body-parser": "^1.20.2",
  "ejs": "^3.1.9",
  "express": "^4.18.2"
},
"devDependencies": {
  "nodemon": "^3.0.1"
}
}

Ejecución del Proyecto

bash
# Iniciar en modo desarrollo
npm run dev

Iniciar en modo producción

ejs
npm start