Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic include (from variable) #93

Open
phplego opened this issue Jan 1, 2013 · 59 comments
Open

Add dynamic include (from variable) #93

phplego opened this issue Jan 1, 2013 · 59 comments

Comments

@phplego
Copy link

phplego commented Jan 1, 2013

For support <% include var_name %>
Please change this code (file ejs.js at line ~ 155):

  if (0 == js.trim().indexOf('include')) {
    var name = js.trim().slice(7).trim();
    if (!filename) throw new Error('filename option is required for includes');
    var path = resolveInclude(name, filename);
    include = read(path, 'utf8');
    include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
    buf.push("' + (function(){" + include + "})() + '");
    js = '';
  }

To this code:

  if (0 == js.trim().indexOf('include')) {
    var name = js.trim().slice(7).trim();
    if (!filename) throw new Error('filename option is required for includes');
    // If it is not path, but variable name (Added)
    if(options[name])
         var path = resolveInclude(options[name], filename);
    else
         var path = resolveInclude(name, filename);
    include = read(path, 'utf8');
    include = exports.parse(include, options); // Added transfer whole options
    buf.push("' + (function(){" + include + "})() + '");
    js = '';
  }

Эти два небольших исправления добавляют возможность использовать переменные в теге
<% include var_name %>

EDIT: File: node_modules/lib/ejs.js at line ~ 155

@johnmarty
Copy link

what file did you make this change in, i also need this functionality

@pwalczyszyn
Copy link

Yeah I would also appreciate this feature 👍

@drewwells
Copy link

This would be incredibly useful.

@carolineBda
Copy link

Same here

@z5h
Copy link

z5h commented Nov 27, 2013

+1

1 similar comment
@marloscarmo
Copy link

+1

@BlackYoup
Copy link

+1, please

@PatrickWelborn
Copy link

+1 :)

@chloe899
Copy link

+1

2 similar comments
@jfhenriques
Copy link

+1

@gaurang171
Copy link

+1

@jasper-lyons
Copy link

This code is wrong btw.

if (0 == js.trim().indexOf('include')) {
    var name = js.trim().slice(7).trim();
    if (!filename) throw new Error('filename option is required for includes');
    // If it is not path, but variable name (Added)
    if(options[name])
         var path = resolveInclude(options[name], filename);
    else
         var path = resolveInclude(name, filename);
    include = read(path, 'utf8');
    include = exports.parse(include, options); // Added transfer whole options
    buf.push("' + (function(){" + include + "})() + '");
    js = '';
  }

In this line,

buf.push("' + (function(){" + include + "})() + '");

buf is a string which does not have a push method. It should be changed to this to work

buf. += "' + (function(){" + include + "})() + '";

For those wondering where to add this code:
node.js - it should be added to node_modules/lib/ejs.js at line:155
in browser - it should be added to the ejs.js file before minification at line:207

I changed the code and made a pull request :)

@pr-nizar
Copy link

+1

@elyran
Copy link

elyran commented Mar 10, 2014

I'd also like to have this functionality. Pull request #156 actually breaks my code for some reason.

@cjmarkham
Copy link

@jasper-lyons buf is an array as defined at the top of the parse function.

@mscdex
Copy link

mscdex commented Apr 2, 2014

I'm not too thrilled about the magic in #156, I'd rather see a separate token (e.g. 'include_dyn') for this behavior to make it very clear what is expected.

@visionmedia Any chance of including this kind of behavior in some way? I dislike maintaining forks for small changes like this and this particular feature seems to be desired by quite a few people.

@elyran
Copy link

elyran commented Apr 2, 2014

@mscdex +1 Absolutely correct!

@jasper-lyons
Copy link

@cjmarkham In the code base I made the fork from buf is most certainly a string, please feel free to have a look.

@mscdex On reflection I agree, I had a need for the functionality and it seemed a lot of others did too so I merely adapted @phplego 's code.

@maggiben
Copy link

+1

2 similar comments
@gimenete
Copy link

+1

@iZhen
Copy link

iZhen commented Apr 26, 2014

+1

@jqsjqs
Copy link

jqsjqs commented Apr 27, 2014

Hi... the original solution works quite well for a single property of the "options" object (i.e., object.property1 is resolvable via options["property1"]). This doesn't work quite so well if I include an object in options that itself has properties. The use case here is that I have 5 or 6 templates I'm using to construct a page and rather include a var for each path at the root of the "options" object, I'd rather be able to specify the property of an object within "options" (i.e., <% include myObj.headers %> ).

I'm in a bit of a hurry tonight, so this won't be the most elegant code, but it does work and covers the original use case. Note that it does split and evaluate literal filenames to determine if they're in the options obj... so if you happen to create an object within "options" like this: options.filename-stem.ejs then whatever value is in there will take precedence. :)

   var resolvedObj = null;
   var objName = name.split(".");
   if (objName) {
       resolvedObj = options;
       for (var idx=0; idx<objName.length; idx++) {
           resolvedObj = resolvedObj[objName[idx]];
           if ( ! resolvedObj) {break;}
       }
   }

   if(resolvedObj)
        var path = resolveInclude(resolvedObj, filename);
   else
        var path = resolveInclude(name, filename);

@AnthonyMDev
Copy link

Using this code, where do I put the variables to user for <% include myVar %> ?

@mhandb
Copy link

mhandb commented May 19, 2014

+1

@dgmike
Copy link

dgmike commented May 19, 2014

What's the difference between <% include file %> and <% include variable %>?

@AnthonyMDev
Copy link

I have a system where users can create dynamic content using a WYSIWYG editor, which is saved in an HTML file. I want to be able to display a list of all of the user generated content at runtime without knowing the files at compile time.

For instance, I'd be able to like to write code in ejs like this:

<% for (i = 0; i <= listOfFiles.length; i++ ) {
file = listOfFiles[i].name;
%>

<% include fileName %>

<% } %>

@blowsie
Copy link

blowsie commented May 30, 2014

+1

@blowsie
Copy link

blowsie commented May 30, 2014

This also seems to be a popular question on stackoverflow.

@cvince
Copy link

cvince commented Jun 2, 2014

+1 --Thanks phplego and jasper-lyons

@kopipejst
Copy link

+1

@jregeimbal
Copy link

+1 Please merge

@ZainShaikh
Copy link

Any update please? I am also looking for the same solution.

@schtauffen
Copy link

Thank you jasper-lyons and phplego!
Working like a charm :) 👍

@mdunisch
Copy link

👍

Please merge - i would totally reduce my code!

@tonmanna
Copy link

tonmanna commented Aug 9, 2014

Not working for me.
I have a problem with options[name] is undefined.
I'm used ejs with Express 4.0 anyone have suggestion?
Thanks you

@Vadorequest
Copy link

This is waiting for more than a year now, it would be great to have such basic feature!

@schtauffen
Copy link

Try Jade, it supports includes AND inheritance through blocks.

I've moved over.

@atinux
Copy link

atinux commented Aug 18, 2014

If you use this solution, think to disable the view cache option in Express.js (true by default in production).

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

@morwalz
Copy link

morwalz commented Aug 18, 2014

I cloned this fork. Still i am unable to make it work. it is said here it is work like <% include var_name %>

So i tried to use it this way <% include mytemp %>

It thorws error E:\node-examples\irobots\nodecontrolbot\express-dashboard\views\mytemp .ejs not found.

Is there spefic any to declare this?

@Rikhart
Copy link

Rikhart commented Aug 27, 2014

I am waiting for more than a year this feature is ready???

@BilalBoulifa
Copy link

+1 very usefull funtionnality, i need it now, it will be nice if we can pass the name of the template as a variable and also some data.

@soenkekluth
Copy link

+1 would be great

@jasper-lyons
Copy link

To note, I've added a simple test in the test cases for this and removed a jshint error occurring.

Does anyone have any further ideas on how this could be implemented safer / more semantically?

For example, with the implementation in my fork, a template including it's self will cause a stack overflow. How would this situation be managed? Remove variables used to resolve templates from the scope of the included templates? Prevent a template from including it's self?

In my experience with templating systems, small as it is, people seem to end up wanting templates to be as composable as functions though i believe that would require some serious changes.

@servanter
Copy link

+1

@ghost
Copy link

ghost commented Dec 9, 2014

pretty please

@chbdetta
Copy link

+1
please merge

@GiantCowFilms
Copy link

+1

1 similar comment
@lklepner
Copy link

lklepner commented Jan 8, 2015

+1

@mde
Copy link
Collaborator

mde commented Jan 8, 2015

Note that v2 of EJS implements include as a plain function call that does the include at runtime: https://github.com/mde/ejs#includes This lets you use whatever variable you want as the pathname.

@lklepner
Copy link

lklepner commented Jan 9, 2015

Many thanks @mde - This is exactly what I was looking for.

@dieka2501
Copy link

wow, it's work 100%, good job.

@brunokrebs
Copy link

This issue exists no more, one can use include as function just like @mde said (thanks by the way). So I think it would be good to close it, don't you think so @tj?

For anyone else who reaches this page, this is how it works:

<%- include(someVar, someObj) %>

Where someVar and someObj is defined, e.g., like this:

app.get('/', function(req, res) {
    res.render('template', {
        someVar: 'partials/index.ejs',
        someObj: {
            name: 'Bruno Krebs'
        }
    });
});

With these lines in you app, you would render template.ejs file and include partials/index.ejs on it. Oh, and partials/index.ejs would receive someObj variable to use it internally.

@mde
Copy link
Collaborator

mde commented Jan 12, 2016

In fact, this entire repo is essentially closed. It's only here for historical reference.

@brunokrebs
Copy link

Oh, I see, sorry.

@subrahmanyabhat
Copy link

If you want dynamic variable in ejs include statement ,just try this
<%- include(variable) %>

@edilsonvilarinho
Copy link

http://ejs.co/
Index

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <%- include('partials/title'); %>

http://localhost:3000/

Error: C:\WorkSpace\umbler\codeingnite-com-gitlab-branch-functionality-1jsRBAE2\app\views\login\login.ejs:6
    4|   <meta charset="utf-8">
    5|   <meta http-equiv="X-UA-Compatible" content="IE=edge">
 >> 6|   <%- include('partials/title'); %>
    7|   <!-- Tell the browser to be responsive to screen width -->
    8|   <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    9|   <!-- Bootstrap 3.3.7 -->

server.js
app.use(express.static('./app/public'));

|--views
|---partials
|------title.ejs

@somdey
Copy link

somdey commented Nov 1, 2017

@edilsonvilarinho I have encountered the same issue with "ejs": "^2.5.7", "express": "^4.16.2". Did you find any solution?

@edilsonvilarinho
Copy link

edilsonvilarinho commented Nov 1, 2017

@smndey
-> app.use(express.static(process.cwd() + '/app/public')); Get it done this way

`var express = require('express');
var consign = require('consign');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');
var expressSession = require('express-session');

var app = express();

app.set( 'view engine' , 'ejs' );
app.set( 'views' , './app/views');
app.set('port', process.env.PORT_SERVER || 3000);

app.use(express.static(process.cwd() + '/app/public'));
app.use(bodyParser.urlencoded({extended : true }));
app.use(expressValidator());
app.use(expressSession({secret:'4JlXXPfp'}));

consign()
.include('app/routes')
.then('config/dbConnection.js')
.then('config/emailConnection.js')
.then('app/utils')
.then('app/models')
.then('app/controllers')
.into(app);

module.exports = app;`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests