3: Rutas, Partials y Bootstrap-TAREAS

🎯 Objetivo de esta parte

Aprender a organizar un proyecto Node.js/Express usando:

  • Carpeta routes/ para separar las rutas del servidor

  • Carpeta views/partials/ para reutilizar componentes HTML

  • Bootstrap para estilos rápidos

  • Estructura profesional de archivos


1️⃣ Estructura final del proyecto

Basado en tus imágenes, esta es la estructura que lograremos:

text
ejs-node/
├── node_modules/
├── routes/
│   └── index.js
├── views/
│   ├── partials/
│   │   ├── head.ejs
│   │   └── header.ejs
│   ├── index.ejs
│   └── new-entry.ejs
├── app.js
├── package.json
└── package-lock.json

2️⃣ Crear la carpeta routes y el archivo index.js

Paso 1: Crear la carpeta routes

bash
mkdir routes

Paso 2: Crear routes/index.js

javascript
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
    res.render('index', {
        title: 'Inicio'
    });
});

router.get('/new-entry', (req, res) => {
    res.render('new-entry', {
        title: 'Nueva Entrada'
    });
});

module.exports = router;

📖 Explicación del código:

ElementoFunción
express.Router()Crea un manejador de rutas independiente
router.get()Define rutas dentro de este módulo
module.exportsExporta el router para usarlo en app.js

3️⃣ Modificar app.js para usar las rutas

Actualiza tu app.js para importar y usar el router:

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

const app = express();

// Configuraciones
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// Middlewares
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Rutas - IMPORTANTE: deben ir después de los middlewares
app.use('/', require('./routes/index'));

// Iniciar servidor
app.listen(app.get('port'), () => {
    console.log(`servidor en puerto ${app.get('port')}`);
});

🔑 Clave: app.use('/', require('./routes/index')) le dice a Express que use todas las rutas definidas en routes/index.js para las URLs que empiecen con /.


4️⃣ Crear la carpeta partials y sus archivos

Crear la carpeta:

bash
mkdir views/partials

Crear views/partials/head.ejs

Este archivo contendrá todo lo relacionado con <head> y Bootstrap:

html
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
    body {
        padding-top: 70px;
    }
</style>

Crear views/partials/header.ejs

Este es el menú de navegación:

html
<nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="/">Express GuestBook</a>
        </div>
        <ul class="nav navbar-nav">
            <li><a href="/">Inicio</a></li>
            <li><a href="/new-entry">Nueva entrada</a></li>
        </ul>
    </div>
</nav>

5️⃣ Crear las vistas principales

Crear views/index.ejs

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><%= title %> | GuestBook</title>
    <% include partials/head %>
</head>
<body class="container">
    <% include partials/header %>
    
    <div class="jumbotron">
        <h1>Libro de Visitas</h1>
        <p>Bienvenido a nuestro libro de visitas. Deja tu mensaje y lee lo que otros han escrito.</p>
        <a href="/new-entry" class="btn btn-primary btn-lg">Escribir mensaje</a>
    </div>
    
    <h2>Mensajes recientes</h2>
    <div class="alert alert-info">
        Próximamente: lista de mensajes
    </div>
</body>
</html>

Crear views/new-entry.ejs

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><%= title %> | GuestBook</title>
    <% include partials/head %>
</head>
<body class="container">
    <% include partials/header %>
    
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3>Escribe un mensaje</h3>
                </div>
                <div class="panel-body">
                    <form action="/add-entry" method="POST">
                        <div class="form-group">
                            <label for="title">Título</label>
                            <input type="text" name="title" id="title" class="form-control" required>
                        </div>
                        <div class="form-group">
                            <label for="message">Mensaje</label>
                            <textarea name="message" id="message" rows="5" class="form-control" required></textarea>
                        </div>
                        <button type="submit" class="btn btn-primary">Guardar mensaje</button>
                        <a href="/" class="btn btn-default">Cancelar</a>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

6️⃣ La sintaxis include en EJS

Observa cómo estamos reutilizando código:

ejs
<% include partials/head %>
<% include partials/header %>

📖 Beneficios de los partials:

  • Reutilización: Un mismo menú en todas las páginas

  • Mantenimiento: Cambias el menú una sola vez

  • Organización: Código más limpio y ordenado


7️⃣ Probar la aplicación

Iniciar el servidor:

bash
npm run dev

Verificar las rutas:

  • http://localhost:3000/ → Página de inicio

  • http://localhost:3000/new-entry → Formulario de nueva entrada


8️⃣ Explicación de las rutas (importante)

En routes/index.js definimos:

RutaMétodoArchivo renderizadoURL amigable
/GETindex.ejsPágina principal
/new-entryGETnew-entry.ejsFormulario

En app.js conectamos el router:

javascript
app.use('/', require('./routes/index'));

Esto significa: "Todas las rutas definidas en routes/index.js serán accesibles desde la raíz /".

Si quisieras un prefijo como /api, harías:

javascript
app.use('/api', require('./routes/index'));
// Ahora las rutas serían /api/ y /api/new-entry

📝 Resumen de lo aprendido

ConceptoCódigo clave
Router de Expressconst router = express.Router()
Exportar rutasmodule.exports = router
Importar rutasapp.use('/', require('./routes/index'))
Incluir partials<% include partials/header %>
Pasar título dinámico{ title: 'Inicio' } y <%= title %>

🎨 Bootstrap incluido

Ya tienes Bootstrap funcionando gracias a partials/head.ejs:

  • Estilos profesionales

  • Navbar fijo

  • Sistema de grillas

  • Botones y paneles con estilo


🚀 Próximo paso: Recibir datos del formulario (POST)

En la siguiente parte aprenderemos a:

  1. Capturar los datos enviados por el formulario usando body-parser

  2. Almacenar mensajes en un arreglo

  3. Mostrar la lista de mensajes en la página principal

  4. Redireccionar después de guardar


🔧 Nota sobre body-parser (actualizada)

Siguiendo tus imágenes, mantenemos body-parser. Pero recuerda que en versiones actuales puedes usar:

javascript
// En lugar de:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Puedes usar directamente:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

Para la próxima parte (formularios POST), necesitaremos urlencoded() para leer los datos del formulario.


✅ Verifica tu estructura

Tu proyecto debería verse así (como en tus imágenes):

text
ejs-node/
├── node_modules/
├── routes/
│   └── index.js
├── views/
│   ├── partials/
│   │   ├── head.ejs
│   │   └── header.ejs
│   ├── index.ejs
│   └── new-entry.ejs
├── app.js
├── package.json
└── package-lock.json

¿Quieres que continúe con la Parte 4 donde procesamos el formulario POST y mostramos los mensajes guardados?

Completar el formulario en new-entry.ejs

Basado en tus imágenes, este es el formulario completo que debes tener en views/new-entry.ejs:

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><%= title %></title>
    <% include partials/head %>
</head>
<body class="container">
    <% include partials/header %>
    
    <div class="col-xs-8 col-xs-offset-2">
        <h2 class="text-center">Write a new Entry</h2>
        
        <form method="POST" action="/add-entry">
            <div class="form-group">
                <label for="title">Title:</label>
                <input 
                    type="text" 
                    name="title" 
                    id="title" 
                    class="form-control"
                    placeholder="Enter a new Title"
                    required>
            </div>

            <div class="form-group">
                <label for="body">Entry Text:</label>
                <textarea 
                    class="form-control"
                    id="body"
                    name="body"
                    rows="5"
                    required></textarea>
            </div>

            <div class="form-group">
                <input type="submit" value="Post Entry" class="btn btn-primary">
                <a href="/" class="btn btn-default">Cancel</a>
            </div>
        </form>
    </div>
</body>
</html>

📖 Explicación del formulario:

AtributoValorFunción
methodPOSTEnvía datos ocultos (no en la URL)
action/add-entryURL donde se enviarán los datos
name="title"-Nombre del campo (lo usaremos en el servidor)
name="body"-Nombre del campo para el mensaje
required-El campo es obligatorio (HTML5)
class="form-control"-Estilo de Bootstrap

Comentarios

Entradas más populares de este blog

Cómo Iniciar un Proyecto Node.js

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

8-Template Engines