mirror of
https://github.com/zebrajr/express.git
synced 2025-12-06 12:19:51 +01:00
Added res.partial(), using the same interface as partial() within a view. Closes #539
This commit is contained in:
parent
509312773d
commit
dd9406cd52
|
|
@ -31,5 +31,10 @@ app.get('/', function(req, res){
|
|||
res.render('ninjas', { ninja: ninja });
|
||||
});
|
||||
|
||||
app.get('/li', function(req, res){
|
||||
res.partial('li', { object: 'Testing', as: 'value' });
|
||||
});
|
||||
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
|
|
|
|||
69
lib/view.js
69
lib/view.js
|
|
@ -18,7 +18,8 @@ var path = require('path')
|
|||
, Partial = require('./view/partial')
|
||||
, union = require('./utils').union
|
||||
, merge = utils.merge
|
||||
, http = require('http');
|
||||
, http = require('http')
|
||||
, res = http.ServerResponse.prototype;
|
||||
|
||||
/**
|
||||
* Memory cache.
|
||||
|
|
@ -42,28 +43,12 @@ exports.Partial = Partial;
|
|||
exports.register = View.register;
|
||||
|
||||
/**
|
||||
* Render `view` partial with the given `options`.
|
||||
* Partial render helper.
|
||||
*
|
||||
* Options:
|
||||
* - `object` Single object with name derived from the view (unless `as` is present)
|
||||
*
|
||||
* - `as` Variable name for each `collection` value, defaults to the view name.
|
||||
* * as: 'something' will add the `something` local variable
|
||||
* * as: this will use the collection value as the template context
|
||||
* * as: global will merge the collection value's properties with `locals`
|
||||
*
|
||||
* - `collection` Array of objects, the name is derived from the view name itself.
|
||||
* For example _video.html_ will have a object _video_ available to it.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Array} options, collection, or object
|
||||
* @return {String}
|
||||
* @api public
|
||||
* @api private
|
||||
*/
|
||||
|
||||
http.ServerResponse.prototype.partial = function(view, options, locals, parent){
|
||||
var self = this;
|
||||
|
||||
function renderPartial(res, view, options, locals, parent){
|
||||
// Inherit parent view extension when not present
|
||||
if (parent && !~view.indexOf('.')) {
|
||||
view += parent.extension;
|
||||
|
|
@ -106,7 +91,7 @@ http.ServerResponse.prototype.partial = function(view, options, locals, parent){
|
|||
options.scope = options.object;
|
||||
}
|
||||
}
|
||||
return self.render(view, options, null, parent);
|
||||
return res.render(view, options, null, parent);
|
||||
}
|
||||
|
||||
// Collection support
|
||||
|
|
@ -130,6 +115,44 @@ http.ServerResponse.prototype.partial = function(view, options, locals, parent){
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` partial with the given `options`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `object` Single object with name derived from the view (unless `as` is present)
|
||||
*
|
||||
* - `as` Variable name for each `collection` value, defaults to the view name.
|
||||
* * as: 'something' will add the `something` local variable
|
||||
* * as: this will use the collection value as the template context
|
||||
* * as: global will merge the collection value's properties with `locals`
|
||||
*
|
||||
* - `collection` Array of objects, the name is derived from the view name itself.
|
||||
* For example _video.html_ will have a object _video_ available to it.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Array} options, collection, or object
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.partial = function(view, options){
|
||||
var app = this.app
|
||||
, options = options || {}
|
||||
, parent = {};
|
||||
|
||||
// root "views" option
|
||||
parent.dirname = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// utilize "view engine" option
|
||||
if (app.set('view engine')) {
|
||||
parent.extension = '.' + app.set('view engine');
|
||||
}
|
||||
|
||||
var str = renderPartial(this, view, options, null, parent);
|
||||
this.send(str, options.headers, options.status);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` with the given `options` and optional callback `fn`.
|
||||
* When a callback function is given a response will _not_ be made
|
||||
|
|
@ -151,7 +174,7 @@ http.ServerResponse.prototype.partial = function(view, options, locals, parent){
|
|||
* @api public
|
||||
*/
|
||||
|
||||
http.ServerResponse.prototype.render = function(view, opts, fn, parent){
|
||||
res.render = function(view, opts, fn, parent){
|
||||
// support callback function as second arg
|
||||
if (typeof opts === 'function') {
|
||||
fn = opts, opts = null;
|
||||
|
|
@ -239,7 +262,7 @@ http.ServerResponse.prototype.render = function(view, opts, fn, parent){
|
|||
|
||||
// Always expose partial() as a local
|
||||
options.partial = function(path, opts){
|
||||
return self.partial(path, opts, options, view);
|
||||
return renderPartial(self, path, opts, options, view);
|
||||
};
|
||||
|
||||
function error(err) {
|
||||
|
|
|
|||
|
|
@ -433,6 +433,8 @@ module.exports = {
|
|||
'test #partial()': function(){
|
||||
var app = create();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
// Auto-assigned local w/ collection option
|
||||
app.get('/', function(req, res){
|
||||
res.render('items.jade', { items: ['one', 'two'] });
|
||||
|
|
@ -474,10 +476,10 @@ module.exports = {
|
|||
|
||||
// as: str collection option
|
||||
app.get('/user', function(req, res){
|
||||
res.send(res.partial('user.jade', {
|
||||
res.partial('user', {
|
||||
as: 'person',
|
||||
collection: [{ name: 'tj' }]
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -486,10 +488,10 @@ module.exports = {
|
|||
|
||||
// as: with object collection
|
||||
app.get('/user/object', function(req, res){
|
||||
res.send(res.partial('user.jade', {
|
||||
res.partial('user.jade', {
|
||||
as: 'person',
|
||||
collection: { 0: { name: 'tj' }, length: 1 }
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -498,11 +500,11 @@ module.exports = {
|
|||
|
||||
// as: this collection option
|
||||
app.get('/person', function(req, res){
|
||||
res.send(res.partial('person.jade', {
|
||||
res.partial('person.jade', {
|
||||
as: this,
|
||||
collection: [{ name: 'tj' }],
|
||||
locals: { label: 'name:' }
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -511,10 +513,10 @@ module.exports = {
|
|||
|
||||
// as: global collection option
|
||||
app.get('/videos', function(req, res){
|
||||
res.send(res.partial('video.jade', {
|
||||
res.partial('video.jade', {
|
||||
as: global,
|
||||
collection: movies
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -523,10 +525,10 @@ module.exports = {
|
|||
|
||||
// Magic variables
|
||||
app.get('/magic', function(req, res){
|
||||
res.send(res.partial('magic.jade', {
|
||||
res.partial('magic.jade', {
|
||||
as: 'word',
|
||||
collection: ['one', 'two', 'three']
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -535,9 +537,9 @@ module.exports = {
|
|||
|
||||
// Non-collection support
|
||||
app.get('/movie', function(req, res){
|
||||
res.send(res.partial('movie.jade', {
|
||||
res.partial('movie.jade', {
|
||||
object: movies[0]
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -545,10 +547,10 @@ module.exports = {
|
|||
{ body: '<li><div class="title">Nightmare Before Christmas</div><div class="director">Tim Burton</div></li>' });
|
||||
|
||||
app.get('/video-global', function(req, res){
|
||||
res.send(res.partial('video.jade', {
|
||||
res.partial('video.jade', {
|
||||
object: movies[0],
|
||||
as: global
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
// Non-collection as: global
|
||||
|
|
@ -557,21 +559,25 @@ module.exports = {
|
|||
{ body: '<p>Tim Burton</p>' });
|
||||
|
||||
app.get('/person-this', function(req, res){
|
||||
res.send(res.partial('person.jade', {
|
||||
res.partial('person.jade', {
|
||||
object: { name: 'tj' },
|
||||
locals: { label: 'User:' },
|
||||
headers: { 'Content-Type': 'text/html; utf-8' },
|
||||
status: 500,
|
||||
as: this
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
// Non-collection as: this
|
||||
assert.response(app,
|
||||
{ url: '/person-this' },
|
||||
{ body: '<p>User: tj</p>' });
|
||||
{ body: '<p>User: tj</p>'
|
||||
, status: 500
|
||||
, headers: { 'Content-Type': 'text/html; utf-8' }});
|
||||
|
||||
// No options
|
||||
app.get('/nothing', function(req, res){
|
||||
res.send(res.partial('hello.ejs'));
|
||||
res.partial('hello.ejs');
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -580,7 +586,7 @@ module.exports = {
|
|||
|
||||
// Path segments + "as"
|
||||
app.get('/role/as', function(req, res){
|
||||
res.send(res.partial('user/role.ejs', { as: 'role', collection: ['admin', 'member'] }));
|
||||
res.partial('user/role.ejs', { as: 'role', collection: ['admin', 'member'] });
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -589,7 +595,7 @@ module.exports = {
|
|||
|
||||
// Deduce name from last segment
|
||||
app.get('/role', function(req, res){
|
||||
res.send(res.partial('user/role.ejs', ['admin', 'member']));
|
||||
res.partial('user/role.ejs', ['admin', 'member']);
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -624,14 +630,16 @@ module.exports = {
|
|||
'test #partial() locals': function(){
|
||||
var app = create();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.send(res.partial('pet-count.jade', {
|
||||
res.partial('pet-count', {
|
||||
locals: {
|
||||
pets: {
|
||||
length: 5
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
@ -658,10 +666,10 @@ module.exports = {
|
|||
var app = create();
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.send(res.partial('movie.jade', {
|
||||
res.partial('movie.jade', {
|
||||
title: 'Foobar'
|
||||
, director: 'Tim Burton'
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user