karellm
karellm

Reputation: 1923

Dynamically load jade templates

I'm working on a small documentation website and the content is stored in files. For instance I have two files chapter1.jade and chapter2.jade in a module1/ directory.

I'd like to read the module1/ directory and dynamically include all the chapterX.jade files in it.

I tried to have do directory = fs.readDirSync('module1/') and then in my view:

each item in directory
  include item

But jade include doesn't support dynamic values (even `include #{item}) doesn't work. Do you have any idea how I could implement this ?

EDIT: I'd like to generate some code under the each loop (anchor for easy linking) so the solution would preferabily be in the view. I could obviously manually add the anchor in the included files but it is not ideal.

Thanks

Upvotes: 0

Views: 2959

Answers (3)

Alfredo cubitos
Alfredo cubitos

Reputation: 171

in addition to kalemas answer you can also write your includes to a file which is included in jade.

in this example I write my includes to include_all.jade. This file is included in a jade file.

If it does not work, check the path ;-)

e.g. in your app.js

var includes = "path/to/include1\n";
includes += "path/to/include2";
...
incPath = "path/to/include_all.jade";

fs.open(incPath,'w',function(err,fd){
if(err){
    throw 'error open file: ' + incPath +" "+ err;
}

var buffer = new Buffer(includes);
 fs.write(fd,buffer,0,buffer.length,null,function(err){
    if (err) 
        throw 'error writing file: ' +err;
    fs.close(fd,function(){
        console.log('file written ' + incPath);
    });
 });
});

in your jade file

include path/to/include_all.jade

Upvotes: 0

karellm
karellm

Reputation: 1923

Here is the short version of what I've done to make it work. It uses the jade Public API.

var directory = __dirname+'/views/bla/'
  , files
  , renderedHTML = '';

if( !fs.existsSync(directory) ) {
  // directory doesn't exist, in my case I want a 404
  return res.status(404).send('404 Not found');
}

// get files in the directory
files = fs.readdirSync(directory);

files.forEach(function(file) {
  var template = jade.compile(fs.readFileSync(directory+file, 'utf8'));

  // some templating
  renderedHTML += '<section><a id="'+file+'" name="'+file+'" class="anchor">&nbsp;</a>'+template()+'</section>';
});

// render the actual view and pass it the pre rendered views
res.render('view', { 
  title: 'View',
  files: files,
  html: renderedHTML
})

And the view just renders the html variable unescaped:

div(class="component-doc-wrap")
  !{html}

Upvotes: 1

jmingov
jmingov

Reputation: 14003

As @user1737909 say, that's not possible using just jade.

The best way to do this (tho) is building a little Express Dynamic (view) Helpers

DEPECATED IN EXPRESS 3.XX

Check these: Jade - way to add dynamic includes

Upvotes: 0

Related Questions