Node and handlebars folder structure - node.js

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'
}));

Related

EJS - include an include from a different directory than the current

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).

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?!

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'

Jade not finding view in different folder

I have a directory like this
/Workspace
/app
app.js
/lib
/public
/styles
*.css
/scripts
*.js
/views
*.jade
from app.js in app, I have the following code:
libPath = __dirname + '/../lib'
... express stuff ...
app.configure(function() {
app.set('view', libPath + '/views')
... express stuff ...
app.use(express.static(libPath + '/public'))
... rest of the app ...
Now, the problem is that Jade can't find any of the views, but all the static assets are found. Thus, app.set('view') isn't working, but express.static is. If I copy the views directory to app, using __dirname + '/views' works fine. Anyone know why this is happening?
doing app.get('view'), I get a directory like this: /Users/jong/Workspace/app/../lib/views. I tried doing the absolute route /Users/jong/Workspace/lib/views as well to no avail. It's just weird that this directory works for static assets but not templates.
You have a mistype, the correct option name is views, not view.
Configure your application like
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', { layout: true });
But the main root of issue is that you seem to misunderstand how express (and the MVC at all) works.
express sends out the static data to the browser, using your express.static configure directive, once the request url matches the existing static file path.
Otherwise, it tries to find any defined route for the requested path and to execute the associated controller (which may or may not use the template engine in turn).
So, in order to show e.g. the index page (even if it has no parameters), given you have an index.js in your views folder, you have to do something like
app.get('/', function (req, res, next) {
res.render('index', {});
});

Resources