EJS - include an include from a different directory than the current - node.js

I need to include an include using EJS templating from a different directory than the one I'm cuurently in. My folder structure is this:
-views
---includes
-----navigation.html
-----footer.html
---page
-----layout.html
When I try to do an <% include includes/navigation.html %> in my page/layout.html it returns:
Could not find include include file.
My view engine setup is below:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', ejs.renderFile);
app.use(expressLayouts);
My question is this: It's to my understanding that app.set('views', path.join(__dirname, 'views')); sets the path for ALL views. But I don't want to just have views/includes because then trying to include other includes that are NOT in views/includes would not work, correct?
How do I include includes in another directory than the current one?

When settings views in your main app, just include the directory you want to use as the "includes" directory:
app.set('views', [path.join(__dirname, 'views'), path.join(__dirname, 'views/includes/')]);

As an alternative, you can do this in your layout.html file:
<%- include('../includes/navigation.html') %>
../ means that you are trying to access the parent directory (from your layout.html file).

Related

Node.js: Path issues for EJS page templates

Using a MEAN environment (Express 4) and EJS as a template engine, I am struggling with a path issue.
Root path of my project: /Users/admin/projectX/
path of pages (.ejs format): /Users/admin/projectX/views/pages
path of partials(.ejs format): /Users/admin/projectX/views/partials
Code samples:
app.set('view engine', 'ejs'); //using ejs as template engine instead of jade
app.set('views', __dirname + '/views'); //defining absolute path of views folder
//sample route for calling index.ejs
app.route('/')
.get(function(req, res) {
res.render('/pages/index'); //index.ejs is located in the pages folder (full path see list above)
});
For some reason I keep getting this error:
Error: Failed to lookup view "/pages/index" in views directory "/Users/admin/projectX/views"
IMHO the path should correctly add up to /Users/admin/projectX/views/pages/index, so why can't it be found?!

Node and handlebars folder structure

I would like to change my file and folder structure a bit, I tried looking for solutions already online but didn't find anything simple and I have a feeling this thing should have an simple solution.
I have currently this
var expressHandlebars = require('express-handlebars');
app.set('views', __dirname + '/views');
app.engine('hbs', expressHandlebars({extname: 'hbs', defaultLayout: 'main'}));
My folder structure is as follows
views
-- frontend
---- (doesn't matter, gulp takes care of this for FE).hbs
-- layouts
---- main.hbs
-- index.hbs
What I wanna archive is to have
views
-- frontend
---- (doesn't matter, gulp takes care of this for FE).hbs
-- backend
---- views
------ index.hbs
---- main.hbs
Basically, I want when I open my views folder in root to have frontend and then backend folder. Backend folder in root should have main layout and then in folders different partials for specific views.
I can add backend folder without issues which changing
app.set('views', __dirname + '/views');
to
app.set('views', __dirname + '/backend');
But how do I swap the that layout is in the root of the views folder?
Just doing this will throw an error because he will look for layout in /backend/layouts/main.hbs and I want it to be in the root.
Also, later I render things by saying res.render('index', data);. Proposed solution should be able to do the same, or at least res.render('views/index', data); because the new views would be in folders.
Any help or tips appreciated.
Nevermind, found it out with help of coworker.
There is an actual option for this which I managed to miss when looking over documentation.
app.engine('hbs', expressHandlebars({
extname: 'hbs',
defaultLayout: 'main',
layoutsDir: './views/backend'
}));

how to set and use partials view paths in node.js + expressJS

I am having problems in setting partial view paths in nodeJs + expressJs. Below is my directory structure.
Directory Structure
packages
--Module1
----Views
------sample.ejs
--sharedModule
----Views
------partials
--------Module1.ejs
--------partialHTML.ejs //able to use in index.ejs
------index.ejs //Used : <% include partials/partialHTML%>
ExpressJS:
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'packages/sharedModule/views'));
I am able to use 'partialHTML.ejs' in index.ejs file using <% include partials/partialHTML%>..
How can i use Module1.ejs files under Module1/view/sample.ejs file ?
You've set packages/sharedModule/views as your views directory, sample.ejs is no where under that dir, it's under another path. That's why it's not found.
In Linux you could create a soft link to point the shared views Module1/views/sharedviews ==> ../../sharedModule/views, then set your Module1 as the root path for views -
app.set('views', path.join(__dirname, 'packages/Module1/views'));
So when you look for any view, it's guaranteed to be found, since now your views dir has both Module1 and sharedModule views.

How to access static js files in EJS?

I have folder structure like
--project
----public
------flowplayer
----views
I want to access files inside js folder from the ejs file inside views. I tried like this but did not work
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
From EJS I am accessing file like this
<script type="text/javascript" src="../public/flowplayer/flowplayer-3.2.13.min.js"></script>
But I am getting error like
http://localhost:3000/connect/125468/test/48B1527B237BB/flowplayer/flowplayer-3.2.13.min.js
Thanks
I was able to solve this by giving the path for the required js file in ejs as '/flowplayer/flowplayer-3.2.13.min.js' instead of '../public/flowplayer/flowplayer-3.2.13.min.js'

Getting 404 for stylesheets and js on sample express-jade project

I have created a simple static page in nodejs using the default express library.
However, when I run it, nodejs is unable to pick up the public files and throws 404 on them.
I believe that the paths that I have given are correct. This is driving me mad. I knoww the problem has to be so tiny and simple to be face-palm worthy but I am unable to find it.
Can you please help me here.
The code is on github at
Rishavs/ComingSoonPage
Thanks for your time and help.
~ Rishav
In your app.js, mount the static files earlier, like so:
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, '/public')));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
Edit: Note the in /public VS public
Like markt mentioned. Your html should not be referencing "public".
<link href="../../styles/site.css" rel="stylesheet" />
vs.
<link href="../../public/styles/site.css" rel="stylesheet" />
In my case it was necessary to specify sub directories, as well as the main "public" static directory, eg:
app.use(express.static(path.join(__dirname, 'public')));
app.use('/public/uploads', express.static(path.join(__dirname, '/public/uploads')));
Also after playing around I found that it made no difference whether the "public" static directory was declared as "/public" or "public" (with or without leading slash).
However it did make a difference if I missed the leading slash from the sub directories, ie this gave me 404:
app.use('public/uploads', express.static(path.join(__dirname, 'public/uploads')));
but this worked ok:
app.use('/public/uploads', express.static(path.join(__dirname, '/public/uploads')));
And of course the old chestnut of making sure permissions are correctly set on the directory!
I am using express 2.5.8 I was able to access public like this:
app.use(express.static(__dirname + '/public'));
Then I noticed that when I have something like this in my layout:
<link rel="stylesheet" type="text/css" href="style.css">
It wasn't serving my style.css as expected, it was expecting me to do something like
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
added the following to my app.js file solved it for me:
app.use(express.static(__dirname + '/public/stylesheets'));
app.use(express.static(__dirname + '/public/javascripts'));
Everything looked like so:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'handlebars');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/public/stylesheets'));
app.use(express.static(__dirname + '/public/javascripts'));
});
The express.static method does not include subfolders recursively. Your scripts and styles are under public/javascripts and public/stylesheets respectively. You have to let express know those folders contain static files that should be served directly, like so:
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use('public/javascripts', express.static(path.join(__dirname, 'public/javascripts')));
app.use('public/stylesheets', express.static(path.join(__dirname, 'public/stylesheets')));
});
The last two lines are the important ones. Note that there are two arguments passed to the app.use method. The first one tells what is the path where the script will be served (a.k.a. what you'd have to type in the browser to get it). The second one is the physical location of the file on the server.

Resources