Vistas con Pug

06/11/2016 Vistas con Pug

Pug

Pug, antes llamado Jade, es el motor de plantillas por defecto de ExpressJS. Al comienzo, puede ser un poco complicado de usar, requiere un periódo de aprendizaje hasta que podamos hacernos con su sintaxis. Pero una vez dominado no querremos dejar de escribir con él, su minimalismo y su obligatoria indentación hacen que generemos un código muy ligero y limpio, por lo tanto, es muy recomendable darle una oportunidad.

Las Vistas

Necesitamos crear varios archivos para las vistas de la lógica que ya tenemos en el Servidor. Dentro del directorio views crearemos una carpeta users, y dentro de ella, ubicaremos dos archivos index.pug y show.pug.

Gulp Watch

Antes de continuar vamos a crear una tarea Gulp que nos va a ayudar a agilizar el proceso de creación de vistas. Al crear Vistas estamos abordando el desarrollo Front-End de la Aplicación, donde tocaremos varios archivos css y js. Con cada modificación de estos archivos que hagamos, será necesario recompilar todo el código lanzando la tarea por defecto que tenemos definida, mediante el comando gulp.

Estar escribiendo constantemente dicho comando puede ser demasiado tedioso, por esta razón, usaremos una oportuna funcionalidad de gulp llamada watch que básicamente se encargará de escuchar los archivos indicados ante cualquier cambio, para seguidamente ejecutar alguna tarea que le indiquemos.

Editaremos nuestro gulpfile.js para añadir dicha tarea, tal que así:

                
                    /**
                     * GULP WATCHER TASKS
                     */
                    gulp.task('watch', () => {
                        gulp.watch('resources/js/**/*.js', ['scripts']);
                        gulp.watch('resources/sass/**/*.scss', ['sass']);
                    });
                
            

Ejecutamos la tarea:

gulp watch

Con esto se estarán observando todos los ficheros .js y .scss del front-end. Cada vez que uno de esos archivos sea modificado, se lanzará la tarea correspondiente con su compilación. De este modo podemos ir realizando cambios en los ficheros del front-end sin preocuparnos por estar compilando los archivos a cada rato.

index.pug

La primera vista que vamos a tratar será la encargada de listar a todos los usuarios de nuestra BBDD. Para ello, editaremos el archivo views/users/index.pug con:

                
                    extends ../layout

                    block content
                        .container
                            h1 Usuarios
                            each user in users
                                .col-xs-6.col-sm-4.col-md-3
                                    .users-box
                                        span.user-name=user.name
                                        span.user-email=user.email
                
            

En esta vista estamos recorriendo una variable users, que será nuestro array de Usuarios. Seguidamente sólo imprimimos su name y su nombre.

No debemos olvidar que ahora hay que modificar el archivo server/controllers/UsersCtrl.js en el método getUsers(), modificaremos la línea res.json() para que ahora sea así:

res.render('users/index', {users: users});

De este modo, en lugar de devolver un JSON, devolveremos una vista (en concreto views/users/index.pug).

Finalmente, añadiremos un poco de estilo. Para ello crearemos un directorio partials dentro del directorio resources. Dentro del directorio partials crearemos un archivo con el nombre _users-box.scss y lo editaremos con el siguiente contenido:

                
                    .users-box{
                        height: 80px;
                        padding: 10px;
                        margin: 10px;
                        box-shadow: -5px 5px 10px black;
                        background: white;
                        &:hover{
                            background: #EEE;
                            cursor: pointer;
                        }
                        .user-name, .user-email{
                            color: black;
                            display:block;
                        }

                        .user-name{
                            font-weight: 600;
                        }
                    }
                
            

No olvidemos importar nuestro fichero en el main.scss!

                
                    ...
                    @import  "../../node_modules/font-awesome/scss/font-awesome";

                    @import  "./partials/users-box";

                    html, body{
                        height: 100%
                    }
                    ...
                
            

Compilamos todo con gulp y accedemos a la url /users para ver el resultado:

Vistas con Pug

Ha quedado genial verdad? Un listado con nuestro usuarios.

show.pug

Para la vista que muestra un único usuario, simplemente pondré esto:

                
                    extends ../layout

                    block content
                        .container
                            .users-box
                                span.user-name=user.name
                                span.user-email=user.email
                
            

Y no nos olvidamos de modificar el controlador UsersCtrl.js, en el método, showUser(), para que devuelva la vista res.render('users/show', {user: user});.

                
                    module.exports.showUser = (req, res) => {
                      var user = User.findOne({email: req.params.email}, function (err, user) {
                          if(err) console.log(err);
                          res.status(200);
                          res.render('users/show', {user: user});
                      });
                    }
                
            

Es importante el método findOne de Mongoose, que nos permitirá obtener un único registro en lugar de un array como ocurre con find().

login.pug

Ahora vamos a proceder a crear la vista del formulario de Login. Crearemos un directorio auth dentro de views y en él crearemos un archivo login.pug. El contenido de esta vista será:

                
                    block content
                        .container
                            form.small-form(action="/auth/login", method="post")
                                h1 Login
                                .form-group
                                    label.control-label Email
                                    input(type="email", name="email" required).form-control
                                .form-group
                                    label.control-label Password
                                    input(type="password", name="password" required).form-control

                                button.btn.btn-primary Submit
                
            
Recuerda que esta vista es servida desde nuestro controlador AuthCtrl.js, mediante el método getLogin(). Este método está enlazado a las rutas gracias al archivo routes/auth.js, donde se define una ruta /login de tipo GET:
                    
                        module.exports.getLogin = (req, res) => {
                            res.render('auth/login', {});
                        };
                    
                

Esto quiere decir que accederemos a dicha ruta mediante la url localhost:3000/auth/login

Agregaremos un poco de estilo. Crearemos un archivo _forms.scss dentro de resources/sass/globals. En este archivo escribiremos:

                
                    .small-form{
                      max-width: 600px;
                      margin: 0 auto;
                    }
                
            

Con esto, visualizaríamos un formulario así:

login form

*Hice un pequeño ajuste al footer para centrarlo (en un archivo resources/sass/globals/_footer.scss como debes de suponer ya).

                
                    footer{
                        margin-top: 30px;
                        text-align: center;
                    }
                
            

Ahora, introduciendo las credenciales adecuadas (email de algún Usuario de la BBDD y de pass 123456) podremos logarnos! Si lo hacemos, en la consola del servidor veremos un mensaje indicando qué usuario se ha logado.

Para cerrar sesión, sólo tenemos que ir a la url /auth/logout y finalizaremos la sesión. También se mostrará un mensaje en la consola del Servidor, indicando qué Usuario ha hecho loggout.

register.pug

Finalmente, nos falta la vista del Registro, un formulario con todos los campos necesarios para que un Usuario se registre en nuestra aplicación. En este archivo register.pug escribiremos:

                
                    extends ../layout

                    block content
                        .container
                            form.small-form(action="/auth/register", method="post")
                                h1 Register

                                .form-group
                                    label.control-label Name
                                    input(type="text", name="name").form-control
                                .form-group
                                    label.control-label Email
                                    input(type="email", name="email").form-control
                                .form-group
                                    label.control-label Password
                                    input(type="password", name="password").form-control
                                .form-group
                                    label.control-label Password confirmation
                                    input(type="password", name="password_confirmation").form-control

                                button.btn.btn-primary Submit
                
            

Y ya esta! Con esta vista, ya podrá registrarse nuestros Usuarios. Este formulario hace un POST a la url /auth/register donde es recibido por nuestro AuthCtrl.js con su método register(). Este método register() guarda al Usuario en la BBDD y seguidamente lo loguea automáticamente.

login form

Nos quedaría realizar validaciones en el servidor para segurarnos de que los datos recibidos cumplen con ciertas normas (el email es un email real, no están vacíos, etc) pero eso lo dejaremos para más adelante. El código, una vez más aquí.

Si tienes alguna duda o sugerencia, no dudes en participar!