Valentyn Shybanov
Valentyn Shybanov

Reputation: 19401

Dynamic templates in EJS (node.js)

Does anybody know a nice solution for including templates, whose names would be known only at run time? EJS's includes allows only to specify exact file/template name.

Use case: I have a article layout and there is article HTML/EJS content in some local file.

To do so I need something like https://github.com/visionmedia/ejs#includes but file name should be taken from locals variable:

Assume I have such handler (simplified):

app.get('/article/:article', function (req, res) {
        var articleContent = req.params.article;
        res.locals.articleContent = 'data/'+articleContent;
        return res.render('article.ejs')
    })

And in article.ejs (assume having ejs-locals):

<% layout('layout') -%>
<section>
  <article class="single-country">
      <% include ???articleContent???  %>
  </article>
</section>

Is there any possibility to do so or is the only option is to load article content and put into articleContent, so available by <%- articleContent %>?

The problem with this solution is that the content of article should be plain html (`<%- -%>' do not interpolate value). So if inside article I need to use any EJS feature, I need to compile/render by myself.

Maybe someone else already knows how this can be done with some dynamic include helper for EJS so no need of additional code?

Upvotes: 3

Views: 6535

Answers (2)

ahoffer
ahoffer

Reputation: 6546

Looks like this is now supported in EJS. It was introduced in v2.0.1: 2015-01-02. The new syntax looks like this

 <%- include(articleContent) %>

To get this to work I had to disable caching in Express by setting:

app.set('view cache', false);

Upvotes: 2

Norberto Bezi
Norberto Bezi

Reputation: 116

You can use a filter like this:

var ejs = require('ejs');
var fs = require('fs');

ejs.filters.article_teaser = function(my_object) {
    return ejs.render(fs.readFileSync(__dirname + '/views/' + my_object.template + '.ejs', 'utf8'), {my_object: my_object});
}

On your template just use:

<%-: article | article_teaser %>

Cheers!

Upvotes: 0

Related Questions