2011-01-17 19 views
43

Estoy usando Express.js (en Node.js) y sé que puede representar una vista con datos personalizados a través del parámetro "locales". (res.render("template", { locals: { foo: "bar" } });)Express.js Ver "globales"

¿Hay alguna forma de tener "globales"? (es decir, datos que son accesibles para cada vista)

Vi view options, pero eso no es recursivo, por lo que reemplaza a los locales que configuré si uso cualquier locals con mi plantilla.

Este es mi caso de uso: quiero que los archivos CSS/JS puedan agregarse por página, y eso es parte de mi diseño principal. El problema es que si no configuro explícitamente esas matrices en cada procesamiento, recibo un error indefinido, por lo que en mi plantilla siempre tengo que hacer el baile typeof css !== "undefined". Además, tengo otras listas de opciones de seleccionar cuadro que no quiero tener que agregar explícitamente a cada uno de mis formularios.

+0

no podría hacerlo mediante la definición de una variable con un alcance global (como por su requieren declaraciones) y luego hacer referencia a él dentro de una de tus llamadas a app.get? – Stephen

+1

Sí, pero aún tengo que pasar explícitamente esos datos en cada llamada de 'render()'. –

+2

¡LOL!Me encontré buscando esta solución, y aquí estoy de nuevo en los zapatos en los que estabas en enero. ¡Gracias por hacer esta pregunta! – Stephen

Respuesta

56

Vale la pena señalar para aquellos que se han encontrado con esta pregunta desde el lanzamiento de Express 3, que el método 'dynamicHelpers' ya no existe.

En su lugar, puede utilizar la función app.locals, que actúa como un objeto en el que puede almacenar valores o funciones, y luego los pone a disposición de las vistas. Por ejemplo: -

// In your app.js etc. 
app.locals.title = "My App"; 
app.locals({ 
    version: 3, 
    somefunction: function() { 
     return "function result"; 
    } 
}); 

// Then in your templates (shown here using a jade template) 

=title 
=version 
=somefunction() 

// Will output 

My App 
3 
function result 

Si necesita acceder al objeto solicitud para extraer información de, usted puede escribir una función middle-ware simple y utilizar los app.settings variable.

Por ejemplo, si está utilizando la conexión-flash para dar mensajes a sus usuarios, es posible hacer algo como esto:

app.use(function(req, res, next) { 
    app.set('error', req.flash('error')); 
    next(); 
}); 

que daría acceso al mensaje de error con = settings.error en tu plantilla

Estos temas se tratan aquí, aunque ligeramente brevemente: http://expressjs.com/api.html#app.locals

Actualización: Express 4

app.locals es ahora un simple JavaScript Object, por lo que cada propiedad tiene que ser fijado uno por uno.

app.locals.version = 3; 
app.locals.somefunction = function() { 
    return "function result"; 
} 

res.locals proporciona la misma funcionalidad exacta, excepto que debe ser usado para datos de solicitud específica en lugar de datos de aplicación. Un objeto o configuración de usuario es un caso de uso común.

res.locals.user = req.isAuthenticated() ? req.user : null; 
res.locals.userSettings = { 
    backgroundColor: 'fff' 
} 
+5

La mejor explicación que he encontrado todavía. Y he recorrido. Gracias. –

+0

app.set ('error', msg) establecería un error para la aplicación ENTERA, no solo para el usuario que realiza la solicitud, ¿o estoy equivocado? – vegetable

+0

Su explicación es fantástica. Pero cuando trato de mostrar las variables globales en mi archivo de Jade usando "= title", no apareció nada. Para esto, debería usar la siguiente sintaxis "# {título}" para mostrar correctamente mi variable. – JohnDoe66

1

La forma más sencilla de lograr esto es crear una variable que represente el conjunto predeterminado de locales para sus vistas. A continuación, cree una función que acepte un objeto, lo fusione con los locales y devuelva el objeto fusionado.

también que pasar todos mis vecinos dentro de un objeto contenedor decir {locals:{g:{prop:val}}} por lo que en mi punto de vista puedo refernce g.prop que acaba de regresar null cuando no se ha establecido, en vez de lanzar un error indefinido.

function default_page_vars(custom_vars){ 
    var vars = { 
     footer: true, 
     host: req.headers.host.split(':')[0], 
     config: this.config 
    }; 

    if(custom_vars){ 
     for(var k in custom_vars){ 
      vars[k] = custom_vars[k]; 
     } 
    } 
    return { 
     g:vars 
    }; 
} 

//within your handler 
response.render(view, { 
    locals: default_page_vars(other_locals) 
}); 
4

Terminé buscando en el código fuente, y he encontrado que esto ahora es posible en las versiones nunca de Express. (hasta ahora, solo disponible a través de GitHub)

+0

¿Te importaría compartir un enlace a la fuente que encontraste? Estoy tratando de hacer lo mismo. Gracias. – luisgo

+1

La versión disponible ahora (v2 +) permite 'app.set (" ver opciones ", {... valores predeterminados ...});' –

+0

@dominic ¿cuáles son esos valores predeterminados? o al menos dónde están listados? – talentedmrjones

10

Hay una manera de tener variables "globales" para las vistas, utilizando ayudantes dinámicos de visualización.

De la guía Express.js:

app.dynamicHelpers (OBJ)

Registros dinámicas ayudantes de vista. Los ayudantes de vista dinámica son simplemente funciones que aceptan req, res y se evalúan en la instancia del servidor antes de que se visualice una vista. El valor de retorno de esta función se convierte en la variable local con la que está asociado .

app.dynamicHelpers ({session: function (req, res) { return req.session;}});

Todos los puntos de vista que ahora tendría sesión disponibles para que los datos de sesión se pueden acceder a través de session.name etc:

se puede encontrar un ejemplo real de cómo usarlos aquí: https://github.com/alessioalex/Nodetuts/tree/master/express_samples (nodo app.js para iniciar la aplicación)

+0

¡Esto funcionó de maravilla para mí, gracias! +1 – talentedmrjones

7

Un ejemplo del mundo real de la utilización de opciones de visualización como el autor menciona:

var app = express.createServer(); 

app.configure(function() { 
    app.set('views', path.join(__dirname, '..', 'views')); 
    app.set('view engine', 'jade'); 
    app.set('view options', { 
    assetVersion: 1 
    }); 

Y luego en mi diseño.Jade (plantilla base para la aplicación en mi caso):

link(rel='stylesheet', href='/static/css/' + assetVersion + '/style.css') 
script(src='/static/js/' + assetVersion + '/script.js') 

Con este pequeño truco, sólo tiene que actualizar la variable de assetVersion un solo lugar para asegurarse de que mis activos no se almacenan en caché en barnices y otros lugares.

0

Esta es una respuesta enterrada, pero finalmente conseguí que funcionara.

1) Este es un ejemplo alrededor del módulo de conexión -flash

2) Añadir una pieza de middleware en server.js/app.js añadir req a locals. Esto permite que la plantilla llame al request.flash() cuando lo necesite. Sin esto, flash() se consume en cada solicitud/redirección que anula el objetivo.

var app = module.exports = express() 
    , flash=require('connect-flash'); 
app.configure(function(){ 
    ... 
    app.use(express.session({ secret: "shhh" })); 

    // Start Router 
    app.use(flash()); 
    app.use(function(req, res, next) { 
    res.locals.request = req; 
    next(); 
    }); 

    app.use(app.router); 
}); 

3) Configuración de su ruta de forma normal (esto es CoffeeScript, pero nada especial)

app.get '/home', (req, res) -> 
    req.flash "info", "this" 
    res.render "#{__dirname}/views/index" 

4) request.flash de llamadas() cuando se desea que los mensajes. Se consumen en cada llamada, así que no CONSOLE.LOG ellos o se irán :-)

!!! 
html 
    head 
    title= config.appTitle 
    include partials/_styles 

    body 
    include partials/_scripts 

    #header 
     a(href="/logout") Logout CURRENTUSER 
     h2= config.appTitle 

    #messages 
     - var flash = request.flash() 
     each flashType in ['info','warn','error'] 
     if flash[flashType] 
      p.flash(class=flashType) 
      = flash[flashType] 


    block content 
     h1 content here 
+0

Recomiendo no pasar todo el objeto de solicitud. // siempre incluye flash app.use (function (req, res, next) { res.locals.flasher = {}; res.locals.flasher.flash = req.flash; res.locals.flasher.session = req.session; next(); }); – Setheron