layout and include #35

Open
guileen opened this Issue Dec 5, 2011 · 36 comments

Comments

Projects
None yet
@guileen

guileen commented Dec 5, 2011

does ejs has features about layout and include?

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Dec 5, 2011

Owner

nope, not yet at least

Owner

tj commented Dec 5, 2011

nope, not yet at least

@dazoe

This comment has been minimized.

Show comment
Hide comment
@dazoe

dazoe Mar 30, 2012

I'd really like to start using express 3 but express 3 requires the templating engine (EJS) handle the layout and includes.

dazoe commented Mar 30, 2012

I'd really like to start using express 3 but express 3 requires the templating engine (EJS) handle the layout and includes.

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Mar 30, 2012

Owner

@dazoe you mean express 3

Owner

tj commented Mar 30, 2012

@dazoe you mean express 3

@dazoe

This comment has been minimized.

Show comment
Hide comment
@dazoe

dazoe Mar 30, 2012

Yeah sorry.

dazoe commented Mar 30, 2012

Yeah sorry.

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Mar 30, 2012

Owner

yeah I'll have to come up with something for ejs, bring partial() back maybe but that doesn't help for layouts

Owner

tj commented Mar 30, 2012

yeah I'll have to come up with something for ejs, bring partial() back maybe but that doesn't help for layouts

@AlgoTrader

This comment has been minimized.

Show comment
Hide comment
@AlgoTrader

AlgoTrader Apr 24, 2012

I desperatly need ejs partials with express 3

I desperatly need ejs partials with express 3

@yohjizzz

This comment has been minimized.

Show comment
Hide comment
@yohjizzz

yohjizzz May 14, 2012

I desperatly need ejs partials with express 3, me too.

I desperatly need ejs partials with express 3, me too.

@slaskis

This comment has been minimized.

Show comment
Hide comment
@slaskis

slaskis May 14, 2012

Contributor

@AlgoTrader @yohjizzz you can use https://github.com/publicclass/express-partials if you're using ejs and express 3. It has partials and layout basically copied from express 2 into a middleware. It's far from perfect but it's a start.

Contributor

slaskis commented May 14, 2012

@AlgoTrader @yohjizzz you can use https://github.com/publicclass/express-partials if you're using ejs and express 3. It has partials and layout basically copied from express 2 into a middleware. It's far from perfect but it's a start.

@yohjizzz

This comment has been minimized.

Show comment
Hide comment

@slaskis Thanks a lot.

@sirwan

This comment has been minimized.

Show comment
Hide comment
@sirwan

sirwan May 14, 2012

I need this too TJ. +1

sirwan commented May 14, 2012

I need this too TJ. +1

@deremer

This comment has been minimized.

Show comment
Hide comment
@deremer

deremer May 21, 2012

I hacked a solution to this that works reasonably well for partials that are small (e.g., a navbar).

I put my partials in their own directory. When my Express app loads, I use fs.readFile to store all the partials in that directory (use fs.readDir) as a string and assign them to an app parameter (e.g., app.set('partials', myPartialsObj) ).

For dynamic content, I put in placeholders like #dynamictext# so that using route middleware I can do a .replace for "#dynamictext#" with as many of these as I need.

Then I pass the partials object to my view (e.g., res.locals.partials = app.set('partials') ) and then I can print the partials as necessary.

It works reasonably well as a hacky solution for very simple partials.

deremer commented May 21, 2012

I hacked a solution to this that works reasonably well for partials that are small (e.g., a navbar).

I put my partials in their own directory. When my Express app loads, I use fs.readFile to store all the partials in that directory (use fs.readDir) as a string and assign them to an app parameter (e.g., app.set('partials', myPartialsObj) ).

For dynamic content, I put in placeholders like #dynamictext# so that using route middleware I can do a .replace for "#dynamictext#" with as many of these as I need.

Then I pass the partials object to my view (e.g., res.locals.partials = app.set('partials') ) and then I can print the partials as necessary.

It works reasonably well as a hacky solution for very simple partials.

@RandomEtc

This comment has been minimized.

Show comment
Hide comment
@RandomEtc

RandomEtc May 26, 2012

I've been experimenting with https://github.com/publicclass/express-partials/ and have a pull request open with layout/include implementations at publicclass/express-partials#1

I also implemented something similar to https://github.com/aseemk/express-blocks and would like to take it further, perhaps using ideas from RENDER in #14. Feedback/assistance welcome!

I've been experimenting with https://github.com/publicclass/express-partials/ and have a pull request open with layout/include implementations at publicclass/express-partials#1

I also implemented something similar to https://github.com/aseemk/express-blocks and would like to take it further, perhaps using ideas from RENDER in #14. Feedback/assistance welcome!

@ForbesLindesay

This comment has been minimized.

Show comment
Hide comment
@ForbesLindesay

ForbesLindesay May 26, 2012

Contributor

Surely layout just involves having a new RenderFileForExpress method that looks like:

renderFile(fileName, options,function(err,result){
    if(err) return cb(err);
    options.body = result;
    renderFile('layout.ejs', options, cb);
});

Partials would just be a case of creating a synchronous renderFile method and automatically passing that as a local to your render method? Do we need anything more complex?

Contributor

ForbesLindesay commented May 26, 2012

Surely layout just involves having a new RenderFileForExpress method that looks like:

renderFile(fileName, options,function(err,result){
    if(err) return cb(err);
    options.body = result;
    renderFile('layout.ejs', options, cb);
});

Partials would just be a case of creating a synchronous renderFile method and automatically passing that as a local to your render method? Do we need anything more complex?

@RandomEtc

This comment has been minimized.

Show comment
Hide comment
@RandomEtc

RandomEtc May 26, 2012

@ForbesLindesay that's good pseudocode for the old layout feature - basically what express-partials offers. To be backwards compatible you want layout.ejs if options.layout is true or undefined, or to use the layout matching the name in options.layout (with correct extension) if the default layout is overridden.

I'm more interested in being able to specify the layout from within a template file, which requires executing the template and then seeing if it requested a layout. Other template engines call this inheritance, so I've implemented it as inherits('parent.ejs') in my express-partials fork. You can do this by rendering templates yourself and passing the results as locals to the top level template but it's nice to have the option to pull as well as push these arrangements, I think, and keep the final layout decisions entirely within templates.

The partial feature could be as simple as you describe (perhaps better name include for that incarnation?) but there are subtleties aside from needing a synchronous call. For example the express-partials implementation does a bit of work to generate an automatic variable name from the file name relative to the current template, and to find a template file from a given partial name (as name/index.ejs, _name.ejs, or ../name/index.ejs for example).

I can totally see why these features have been removed from core express, and made specific to the template engine. I hope we can find a way to get some of them into EJS as @visionmedia has for Jade, and also to make sure that the API for accessing the required app settings (view engine, views path, etc) is documented and stable before Express hits 3.0 final.

@ForbesLindesay that's good pseudocode for the old layout feature - basically what express-partials offers. To be backwards compatible you want layout.ejs if options.layout is true or undefined, or to use the layout matching the name in options.layout (with correct extension) if the default layout is overridden.

I'm more interested in being able to specify the layout from within a template file, which requires executing the template and then seeing if it requested a layout. Other template engines call this inheritance, so I've implemented it as inherits('parent.ejs') in my express-partials fork. You can do this by rendering templates yourself and passing the results as locals to the top level template but it's nice to have the option to pull as well as push these arrangements, I think, and keep the final layout decisions entirely within templates.

The partial feature could be as simple as you describe (perhaps better name include for that incarnation?) but there are subtleties aside from needing a synchronous call. For example the express-partials implementation does a bit of work to generate an automatic variable name from the file name relative to the current template, and to find a template file from a given partial name (as name/index.ejs, _name.ejs, or ../name/index.ejs for example).

I can totally see why these features have been removed from core express, and made specific to the template engine. I hope we can find a way to get some of them into EJS as @visionmedia has for Jade, and also to make sure that the API for accessing the required app settings (view engine, views path, etc) is documented and stable before Express hits 3.0 final.

@RandomEtc

This comment has been minimized.

Show comment
Hide comment
@RandomEtc

RandomEtc May 26, 2012

I finished up and published my fork of express-partials as ejs-locals - with support for layout, include, block and partial. Feedback welcome: https://github.com/randometc/ejs-locals/

update: fixed link

I finished up and published my fork of express-partials as ejs-locals - with support for layout, include, block and partial. Feedback welcome: https://github.com/randometc/ejs-locals/

update: fixed link

@gagginaspinnata

This comment has been minimized.

Show comment
Hide comment
@gagginaspinnata

gagginaspinnata Jul 29, 2012

Please bring back ejs layout :(

Please bring back ejs layout :(

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Jul 29, 2012

Owner

ejs has includes now but yup i'll put some effort into the extends part soonish

Owner

tj commented Jul 29, 2012

ejs has includes now but yup i'll put some effort into the extends part soonish

@ForbesLindesay

This comment has been minimized.

Show comment
Hide comment
@ForbesLindesay

ForbesLindesay Jul 29, 2012

Contributor

The way I implimented it in my fork of EJS (called QEJS) was to give the templates two local functions. These could be includes and extends. includes renders a child template and returns it, while extends just marks the fact that a given template extends another template.

<% extends('layout') %>
<%- include('child-template') %>

The include function obviously just needs to be a synchronous template renderer (or have some simple magic to make it look synchronous).

The extends function just looks like:

var extending = null;
function extends(tmpl) {
  extending = templ;
}

Then you render function is aproximately:

renderFile(fileName, options,function(err,result){
    if(err) return cb(err);
    if (extending) {
      options.contents = result;
      renderFile(extending, options, cb);
    } else {
      cb(null, result);
    }
});

I'm not sure how efficient this is, but it's very simple, and work could probably be done to optimise it.

Contributor

ForbesLindesay commented Jul 29, 2012

The way I implimented it in my fork of EJS (called QEJS) was to give the templates two local functions. These could be includes and extends. includes renders a child template and returns it, while extends just marks the fact that a given template extends another template.

<% extends('layout') %>
<%- include('child-template') %>

The include function obviously just needs to be a synchronous template renderer (or have some simple magic to make it look synchronous).

The extends function just looks like:

var extending = null;
function extends(tmpl) {
  extending = templ;
}

Then you render function is aproximately:

renderFile(fileName, options,function(err,result){
    if(err) return cb(err);
    if (extending) {
      options.contents = result;
      renderFile(extending, options, cb);
    } else {
      cb(null, result);
    }
});

I'm not sure how efficient this is, but it's very simple, and work could probably be done to optimise it.

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Jul 29, 2012

Owner

the include I added is at compile time like jade so the sync IO doesn't matter, but it would be nice to still have a function and cache that sync read for more dynamic stuff, more like the old partial()

Owner

tj commented Jul 29, 2012

the include I added is at compile time like jade so the sync IO doesn't matter, but it would be nice to still have a function and cache that sync read for more dynamic stuff, more like the old partial()

@ForbesLindesay

This comment has been minimized.

Show comment
Hide comment
@ForbesLindesay

ForbesLindesay Jul 29, 2012

Contributor

Yeh, I got round the problem by supporting asynchronous operations in the template, but I think doing it at compile time is probably much more efficient. I'm just proposing that sticking to the functional syntax is nice, less new stuff to learn syntax wise. That's what I like about EJS over mustache or Jade like templates.

Contributor

ForbesLindesay commented Jul 29, 2012

Yeh, I got round the problem by supporting asynchronous operations in the template, but I think doing it at compile time is probably much more efficient. I'm just proposing that sticking to the functional syntax is nice, less new stuff to learn syntax wise. That's what I like about EJS over mustache or Jade like templates.

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Jul 29, 2012

Owner

yup, doing any IO at all is unnecessary in most cases. I agree though a simple function is nicer than some new concept. What I used to do with partials is that the first read was sync but all subsequent ones in production were cached, so it's convenient and more efficient than async anyway, we could do similar here without reworking all the internals

Owner

tj commented Jul 29, 2012

yup, doing any IO at all is unnecessary in most cases. I agree though a simple function is nicer than some new concept. What I used to do with partials is that the first read was sync but all subsequent ones in production were cached, so it's convenient and more efficient than async anyway, we could do similar here without reworking all the internals

@ForbesLindesay

This comment has been minimized.

Show comment
Hide comment
@ForbesLindesay

ForbesLindesay Jul 29, 2012

Contributor

Sounds good to me.

Contributor

ForbesLindesay commented Jul 29, 2012

Sounds good to me.

@nickpoorman

This comment has been minimized.

Show comment
Hide comment
@nickpoorman

nickpoorman Aug 1, 2012

It would be nice to have a layout.

It would be nice to have a layout.

@fzaninotto

This comment has been minimized.

Show comment
Hide comment
@fzaninotto

fzaninotto Aug 6, 2012

Looking forward to seeing these two features in ejs soon. Any way we can help?

Looking forward to seeing these two features in ejs soon. Any way we can help?

@pixelfreak

This comment has been minimized.

Show comment
Hide comment
@pixelfreak

pixelfreak Aug 14, 2012

Another upvote here. I am looking to upgrade to Express 3 soon. For now, should I rely on include or wait for a more proper implementation? Thanks.

Another upvote here. I am looking to upgrade to Express 3 soon. For now, should I rely on include or wait for a more proper implementation? Thanks.

@jpravetz

This comment has been minimized.

Show comment
Hide comment
@jpravetz

jpravetz Aug 17, 2012

Another upvote for layout and partials. The ejs locals package looks to be lightweight and sufficient, and adds some functionality. Thoughts on whether this functionality needs to be part of Express or can be farmed out to a separate module?

Another upvote for layout and partials. The ejs locals package looks to be lightweight and sufficient, and adds some functionality. Thoughts on whether this functionality needs to be part of Express or can be farmed out to a separate module?

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Aug 17, 2012

Owner

there's nothing improper about include, but yeah a partial() / layout would be nice

Owner

tj commented Aug 17, 2012

there's nothing improper about include, but yeah a partial() / layout would be nice

@pixelfreak

This comment has been minimized.

Show comment
Hide comment
@pixelfreak

pixelfreak Aug 22, 2012

Sorry, didn't mean improper, I meant to say incomplete. Anyway, I have decided to learn Jade instead since that already has block/extend/include support

Sorry, didn't mean improper, I meant to say incomplete. Anyway, I have decided to learn Jade instead since that already has block/extend/include support

@VTXCoder

This comment has been minimized.

Show comment
Hide comment
@VTXCoder

VTXCoder Aug 28, 2012

I have tried using the ejs-locals package and having numerous path issues and then used eddyystop pull which has different issues. Anyway this has stopped me in my tracks. I love how EJS has the same format as the client JS code (especially if you are using underscore templates on the client) and am not interested in using a different syntax such as Jade. Looking forward to having EJS working again in Express 3! Thanks. Unfortunately I am pretty new to node so can't contribute to the solution.

I have tried using the ejs-locals package and having numerous path issues and then used eddyystop pull which has different issues. Anyway this has stopped me in my tracks. I love how EJS has the same format as the client JS code (especially if you are using underscore templates on the client) and am not interested in using a different syntax such as Jade. Looking forward to having EJS working again in Express 3! Thanks. Unfortunately I am pretty new to node so can't contribute to the solution.

@medanat

This comment has been minimized.

Show comment
Hide comment
@medanat

medanat Sep 3, 2012

I'd like to have layout brought back as well.

medanat commented Sep 3, 2012

I'd like to have layout brought back as well.

@chovy

This comment has been minimized.

Show comment
Hide comment
@chovy

chovy Sep 17, 2012

please add support for ejs layouts and partials in 3.x -- can't believe someone thought it was a good idea to remove it and require everyone to use jade for this functionality.

chovy commented Sep 17, 2012

please add support for ejs layouts and partials in 3.x -- can't believe someone thought it was a good idea to remove it and require everyone to use jade for this functionality.

@tj

This comment has been minimized.

Show comment
Hide comment
@tj

tj Sep 18, 2012

Owner

@chovy it has nothing to do with Jade... these are concepts that engines should provide, in their own opinionated ways

Owner

tj commented Sep 18, 2012

@chovy it has nothing to do with Jade... these are concepts that engines should provide, in their own opinionated ways

@wemakeweb

This comment has been minimized.

Show comment
Hide comment
@wemakeweb

wemakeweb Feb 14, 2013

whats the status of this?

whats the status of this?

@ForbesLindesay

This comment has been minimized.

Show comment
Hide comment
@ForbesLindesay

ForbesLindesay Feb 14, 2013

Contributor

We've specified what we want, but that was 3 months back and I was hoping to get time to work on it but real life caught up. We have includes but not extends or partials as specced in #69 (comment) (and a few subsequent comments)

Contributor

ForbesLindesay commented Feb 14, 2013

We've specified what we want, but that was 3 months back and I was hoping to get time to work on it but real life caught up. We have includes but not extends or partials as specced in #69 (comment) (and a few subsequent comments)

@dctr

This comment has been minimized.

Show comment
Hide comment
@niftylettuce

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment