Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a variable in a Jade include

I'm working with Jade and Express and I would like to use a variable in my include statement. For example:

app.js

app.get('/admin', function (req, res) {
  var Admin = require('./routes/admin/app').Admin;

  res.render(Admin.view, {
    title: 'Admin',
    page: 'admin'
  });
});

layout.jade

- var templates = page + '/templates/'

include templates

When I do this I get the error EBADF, Bad file descriptor 'templates.jade'

I even tried

include #{templates}

to no avail.

like image 637
Spencer Carnage Avatar asked Aug 26 '12 18:08

Spencer Carnage


4 Answers

AFAIK JADE does not support dynamic including. What I suggest is to "include" outside the template, i.e.

app.js

app.get('/admin', function (req, res) {
    var Admin = require('./routes/admin/app').Admin;
    var page = 'admin';

    var templates = page + '/templates/';

    // render template and store the result in html variable
    res.render(templates, function(err, html) {

        res.render(Admin.view, {
            title: 'Admin',
            page: page,
            html: html
        });

    });

});

layout.jade

|!{ html }
like image 133
freakish Avatar answered Sep 21 '22 19:09

freakish


this also works:

//controller
var jade = require('jade');
res.render('show', {templateRender: jade.renderFile});


//template
!= templateRender('my/path/'+dynamic+'.jade', options)

This probably will not increase the performance that you would expect from using the 'view cache' setting (it's on by default in NODE_ENV === 'production'). Or even break the app (e.g. if files are not available on the hard drive while deploying new code). Also trying to use this trick in a client-side or isomorphic app will not work because the template can not be compiled.

like image 41
antpaw Avatar answered Sep 20 '22 19:09

antpaw


Found this page googling for the same question, but in a different context, so thought I'd put my solution (read: workaround) here for posterity:

I wanted to surround my include with more context pulled from the variable, e.g. (simplified):

- var templates = page + '/templates/'
- var headid = page + 'head'
- var imgsrc = '/images/' + page
div(id=headid)    
  h1 #{page}
  img(src=imgsrc)
div(id=page)
  include templates

Since that doesn't work (Jade doesn't support dynamic includes, as noted by freakish), I hybridized with a mixin:

(Edit– a little more elegant than my previous workaround:)

mixin page1
  include page1/templates

mixin page2
  include page2/templates

...

- for (var i = 0; i < 3; i++)
  - var page = 'page' + i
  - var headid = page + 'head'
  - var imgsrc = '/images/' + page
  div(id=headid)    
    h1 #{page}
    img(src=imgsrc)
  div(id=page)
    +page

My previous answer:

mixin templates(page)
  - var headid = page + 'head'
  - var imgsrc = '/images/' + page
  div(id=headid)    
    h1 #{page}
    img(src=imgsrc)

+templates('page1')
#page1
  include page1/templates/

+templates('page2')
#page2
  include page2/templates/

...

It's not elegant, and it won't work if you need to include more than a few things this way, but at least part of the Jade is dynamic.

like image 7
Frijol Avatar answered Sep 22 '22 19:09

Frijol


Why do not use jade inheritance?

Render what you want at middleware level:

res.render('templates/' + template_name + '.jade')

Write common common.jade:

h1 This is a page
.container
  block sublevel
    h2 Default content

Then write file that extends common.jade:

extends common.jade
block sublevel
  h2 Some things are here
like image 1
user2956171 Avatar answered Sep 22 '22 19:09

user2956171