2010-08-30 6 views
11

Tengo un servidor básico Express:¿Cómo paso el contenido de una plantilla a un diseño en Express?

// server.js: 
var Express = require('express'); 
app = Express.createServer(); 
app.configure(function(){ 
    app.set('views', Path.join(__dirname, 'views')); 
    app.set('view engine', 'jade'); 
    app.set('view options'); 
}); 
app.get('/', function (request, response) { 
    response.render('welcome', { 
    locals: {some: 'Locals'} 
    }); 
}); 

Con un diseño de jade básica:

// views/layout.jade: 
!!! 5 
html(lang='en') 
    head 
    title= pageTitle 
    body 
    h1= pageTitle 
    aside(id="sidebar")= sidebarContent 
    #content 
     #{body} 

Y una simple página:

# views/welcome.jade: 
// How do I pass pageTitle and sidebarContent out to the layout from here? 
p 
    Welcome to my fine site! 

(En Rails, esto podría ser algo así como content_for o una simple variable de instancia.)

+0

Si bien es un CMS basado en DocPad, tal vez usted encontrará que es útil, ya que tiene soporte para los diseños y jade. https://github.com/balupton/docpad – balupton

Respuesta

19

con la punta por encima de unos dynamicHelpers, y la magia de los cierres, he encontrado una solución bastante elegante que funciona sin la participación del objeto de la petición. El truco consiste en envolver la variable de título de la página en un cierre que proporciona una función get() y set() a su alrededor, y convertir ese objeto contendor en el resultado del helper dinámico page_title.

Crear una property.js:

exports.create = function() { 
    var value = null; 
    return { 
     get: function() { 
      return value; 
     }, 
     set: function (new_value) { 
      value = new_value; 
     } 
    }; 
} 

Así que llamar a create() devuelve un objeto con un método set() get() y en él, que obtiene y pone la variable de cierre.

Luego, en el código de configuración de la aplicación:

var property = require("./property.js"); 
    app.dynamicHelpers ({ 
     page_title: function() { 
     return property.create(); 
     } 
    }); 

Dado que el valor del ayudante dinámica es el resultado de llamar a su función, en su opinión y la plantilla, la variable page_title será el objeto envolvente con el get () y set() funciones.

En su opinión, a continuación, puede decir:

- page_title.set ("my specific page title"); 

Y en su diseño:

title= page_title.get() 

Para simplificar esto un poco más allá, añadiendo esto a property.js:

exports.creator = function() { 
    return function() { 
     return exports.create(); 
    }; 
} 

Le permite simplificar el bloque de declaración de ayuda dinámico a esto:

 var property = require("./property.js"); 
     app.dynamicHelpers ({ 
      page_title: property.creator() 
     }); 
+0

¡Uno de los usos más prácticos de los cierres que he encontrado! –

+0

¿Cómo usaste esto en la vista? Me gusta esta idea, pero para mí la función set() nunca se llama y get() siempre es nula. – qodeninja

0

Pase en los locales: {some: 'Locals', pageTitle: 'Welcome!'}

+0

No tengo 'locales' dentro de esa plantilla. Tendría que mantener un mapa de '{ruta de la plantilla: título de la página}' y buscar el título de la página antes de renderizar. Debe haber una forma de especificarlo desde * dentro * de la plantilla misma. –

5

Express no tiene una noción preconcebida de "bloques" o lo que ellos llaman que en los carriles, pero se puede utilizar una combinación de ayudantes() y dynamicHelpers() para lograr algo similar http://expressjs.com/guide.html#app-helpers-obj-

los locales pasaron

están disponibles tanto para el diseño y la vista de página, aunque

+0

¿Entonces la idea sería agregar un ayudante dinámico que almacene 'pageTitle' en la solicitud, que el diseño pueda leer? Eso suena como una buena solución. ¡Incluso podría envolverlo como un middleware y publicarlo! –

1

Puede hacerlo utilizando este pequeño fragmento.

prop.js:

var hash = {}; 
module.exports = function() { 
    return { 
     set: function(key, val) { hash[key] = val }, 
     get: function(key) { return hash[key] } 
    }; 
}; 

servidor.JS:

app.dynamicHelpers({ prop: require(__dirname + '/views/helpers/prop') }); 

Vista:

<% prop.set('foo', 'bar') %> 

Diseño:

<%= prop.get('foo') %> 
2

layout.jade

# the following function is a safe getter/setter for locals 
- function pagevar(key, value) { var undef; return (value===undef) ? locals[key] || null : locals[key] = value; } 
block config 
    #intended as a non-rendered block so that locals can be overridden. 
    # put your defaults here... - use append in the child view 
!!! 
html 
    head 
    title=pagevar('title') 
    meta(name='description',content=pagevar('description')) 
...

page.jade

append config 
    - locals.title = 'override'; 
    - locals.description = 'override 2'; 
    - pagevars('somekey', 'some value'); 
...

Easy peazy.

0

Por expreso 3 Plantilla agnóstico, funciona bien con express-partials

app.use (req, res, next)-> 
    req.locals = {} unless req.locals 

    res.locals.content_for = (k, v = null)-> 
    if !v 
     req.locals[k] 
    else 
     req.locals[k] = v 

    next() 
Cuestiones relacionadas