2010-08-30 5 views
11

Ich habe einen grundlegenden Express-Server:Wie übertrage ich Inhalt von einer Vorlage an ein Layout in 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'} 
    }); 
}); 

Mit einem grundlegenden Jade Layout:

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

Und eine einfache Seite:

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

(In Rails, das etwas sein könnte, wie content_for oder eine einfache Instanzvariable.)

+0

Während es ein CMS basiert auf DocPad, vielleicht finden Sie es nützlich, da es für Layouts und Jade in Unterstützung gebaut hat. https://github.com/balupton/docpad – balupton

Antwort

19

Mit dem Tipp über DynamicHelpers, und die Magie der Verschlüsse, fand ich eine ziemlich elegante Lösung, die funktioniert, ohne die Anfrage Objekt beteiligt. Der Trick besteht darin, die Seitentitelvariable in eine Closure zu packen, die eine get() - und set() - Funktion umgibt, und dieses Wrapper-Objekt zum Ergebnis des dynamischen Helfer page_title zu machen.

eine property.js erstellen:

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

So erstellen Aufruf() gibt ein Objekt mit einer get() und set() Methode darauf, dass bekommen und die Schließung Variable gesetzt.

Dann in Ihrem App-Code-Setup:

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

Da die dynamischen Helfer Wert ist das Ergebnis der Funktion des Aufrufs aus Ihrer Sicht und Vorlage, die page_title Variable wird das Wrapper-Objekt mit der get sein () und set() Funktionen.

Ihrer Ansicht nach kann man dann sagen:

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

Und in Ihrem Layout:

title= page_title.get() 

dies ein bisschen weiter zu vereinfachen, und fügte hinzu, dies zu property.js:

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

Ermöglicht Ihnen, den Deklarationsblock für dynamische Helfer zu vereinfachen:

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

Einer der praktischsten Verwendungen von Verschlüssen, auf die ich gestoßen bin! –

+0

Wie hast du das eigentlich in der Ansicht benutzt? Ich mag diese Idee, aber für mich wird die Funktion set() nie aufgerufen und get() ist immer null. – qodeninja

0

Pass es in Einheimischen: {some: 'Locals', pageTitle: 'Welcome!'}

+0

Ich habe keine "Einheimischen" aus dieser Vorlage. Ich müsste eine Karte von {{Vorlagenpfad: Seitentitel}} behalten und den Seitentitel vor dem Rendern nachschlagen. Es muss eine Möglichkeit geben, es von * innerhalb * der Vorlage selbst zu spezifizieren. –

5

Express eine vorgefasste Meinung von „Blöcke“ dass das, was sie nennen in in Schienen haben oder nicht, aber Sie können eine Kombination von Helfern() und dynamicHelpers() ähnlich, etwas zu erreichen verwenden http://expressjs.com/guide.html#app-helpers-obj-

Locals übergeben sind sowohl für das Layout und die Seitenansicht obwohl

+0

Die Idee wäre also, einen dynamischen Helfer hinzuzufügen, der 'pageTitle' in der Anfrage speichert, die das Layout dann auslesen kann? Das klingt nach einer guten Lösung. Ich könnte es sogar als Middleware einpacken und es veröffentlichen! –

1

Sie können das tun, indem Sie dieses kleine Snippet verwenden.

prop.js:

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

Server.js:

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

Ausblick:

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

Layout:

<%= 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'); 
...

Einfach peazy.

0

Für Express 3 template Agnostiker, funktioniert gut mit 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() 
Verwandte Themen