Preprocesar variables de templates en express framework (nodejs)
Bien, el caso de uso es el siguiente: tenemos varios templates en los que queremos mostrar mensajes al usuario si los hubiera.
Lo normal seria hacer algo así a la hora de renderizar un template:
Para la página principal:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
app.get('index', function (req, res) { var messages = req.flash(); var render_options = { titulo: "Página principal" }; if (messages.error || messages.info || messages.success) { if (messages.error) messages.hasError = messages.error.length > 0; if (messages.info) messages.hasInfo = messages.info.length > 0; if (messages.success) messages.hasSuccess = messages.success.length > 0; render_options.messages = messages; } res.render('index', render_options); }); |
Para la página del usuario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
app.get('user', function (req, res) { var messages = req.flash(); var render_options = { titulo: "Perfil de " + req.session.user.name }; if (messages.error || messages.info || messages.success) { if (messages.error) messages.hasError = messages.error.length > 0; if (messages.info) messages.hasInfo = messages.info.length > 0; if (messages.success) messages.hasSuccess = messages.success.length > 0; render_options.messages = messages; } res.render('index', render_options); }); |
Bien, la idea se aprecia, constantemente tenemos que trabajarnos la variable “messages” y si hay mensajes la incluimos en las opciones de renderizado del template.
¿El inconveniente? el código se repite, lo que lo hace poco mantenible y ensucia. Solo por dar un ejemplo, podés ver que estamos preparando errores del tipo “error“, “info” y “success“, y si quisieras agregar un nuevo tipo de error llamado “warning“, te las verías p… negras. Bueno se entiende el inconveniente.
Solución: Encapsular en un preprocesador
Express nos da la posibilidad de preparar variables que van a parar al template haciendo uso de app.use() y res.locals.
NOTA importante: da igual el sistema de templates que uses: Jade, Hogan.js, Mustache, Handlebars, etc. Express es agnóstico en este sentido a la hora de preparar variables. Un puntazo.
Bueno, como decía, podemos agregar un app.use() en app.configure(function () {}); (suele estar en app.js, la base de tu aplicación).
Acá está el ejemplo. Hemos quitado la lógica de tratamiento de mensajes y la hemos colocado en este middleware (si, es uno de esos famosos):
1 2 3 4 5 6 7 8 9 10 11 12 |
app.use(function (req, res, next) { var messages = req.flash(); if (messages.error || messages.info || messages.success) { if (messages.error) messages.hasError = messages.error.length > 0; if (messages.info) messages.hasInfo = messages.info.length > 0; if (messages.success) messages.hasSuccess = messages.success.length > 0; res.locals.messages = messages; } next(); }); |
Lo mas notable del código anterior es que hemos asignado el resultado a res.locals.messages. res.locals, va a “mergearse” con las variables que uses en res.render() antes de llamar al template.
NOTA: next(); es necesario para que el flow de ejecución siga adelante.
Hecho lo anterior, les presento las versiones simplificadas de los ejemplos que di al principio:
1 2 3 4 5 6 |
app.get('index', function (req, res) { var render_options = { titulo: "Página principal" }; res.render('index', render_options); }); |
1 2 3 4 5 6 |
app.get('user', function (req, res) { var render_options = { titulo: "Perfil de " + req.session.user.name }; res.render('index', render_options); }); |
Mucho mejor ¿no?
Chau!
Lo mas notable del código anterior es que hemos asignado el resultado a res.locals.messages. res.locals, va a “mergearse” con las variables que uses en res.render() antes de llamar al template. NOTA: next(); es necesario para que el flow de ejecución siga adelante.
Y este comentario? solo citas lo que he escrito.