How do you render when organising project by feature? - node.js

I have changed the structure of my project and now I group stuff by features. Instead of putting all routes in "Routes", all controllers in "controllers", etc.
I find the new way much better but I have found that for rendering the local file, as it is not anymore in the "views" folder, I have to do:
res.render("../auth/login");// presumably we are in views so we go up and then auth/login.ejs
And inside login.ejs I have to do:
<%include ../views/partials/header %>
Is this the way to follow when using project structure by feature?

The folder express uses for templates is called views, and is enabled by default:
app.set('views', './views'); //this code runs when you call: var app = express();
If you want to set multiple locations that express will look for views, you can do so by calling:
app.set('views', __dirname + '/foo');
Now, express will look in the views and foo folders for templates to use.
If you want to set multiple folders, you can call app.set multiple times, or simply pass an array of folders to app.set:
app.set('views', [__dirname + '/foo', __dirname + '/bar']);
Now, express will look in the views, foo, and bar folders for templates.
Lets say you have foo.ejs in the foo folder and bar.ejs in the bar folder. You can access these templates like this:
<%- include 'foo' %>
<%- include 'bar' %>
This question was a good reference for your problem.

Related

How to pass data from Node server to ejs header

I am trying to create a Node website with a header ejs file that is included on each page.
When I load my index.ejs page, I would also like to pass a variable from my server to my header page.
I could be wrong, but it seems like the best way to do that is to pass that variable from the server, to the index page, then to the header.
Currently, the only example I've seen of this is the following code snippet:
<%- include("header",{title:"your_title"}) %>
The catch is that I would need to replace "your_title" with a title variable that I set serverside.
Is there a way to do this?
My hunch is that it may look like the following:
<% runHeader = function(title){ %>
<%- include('../partials/header', {title: title}); %>
<%}; %>
Unfortunately, include does not seem to run properly here, and the header does not load at all.
Any help would be much appreciated!
so the best way I found for this to work is to make a a "views" folder under your project folder. The views folder will have an ejs file with the name of "title.ejs" the call should then look like <%- include("title") -%>this will look for the ejs file in the same directory. I'd say in the title file add some sample HTML then everything should work.
Make sure that you have NPM installed ejs, then in nodefile use const ejs = require("ejs"); and app.set('view engine', 'ejs'); and app.use(express.static("public"));in the same node.js file.
Hope this makes sense and good luck.

Nodejs Express handlebars how to include .hbs inside another .hbs without templates

How could I include .hbs inside another .hbs without templates? I'm using a component based architecture for Nodejs wih Express and I need to include hbs files with content for use the {{values}} in both, html and js sides without duplicating anything and clean.
I tried using partialsDir like this:
app.engine('.hbs', exphbs({
defaultLayout: 'layout',
extname: '.hbs',
layoutsDir: path.join(__dirname),
partialsDir: [
path.join(__dirname, 'dashboard', '_public', 'main'),
path.join(__dirname, 'home', '_public', 'main')
]
}));
but it gets all of the scripts of all of the views of all of the routes. And using {{>viewScript}} (templates) it load all the .hbs (when I go to home I have the home partial .hbs, when I go to dashboard I have the home and the dashboard partials .hbs so that not works for me.
I tried with src, but it doesn't work (mime error)
<script src="viewScript.hbs"></script>
I can combine both .hbs with its own js inside one .hbs file, ok, but I wanted to keep those pieces separated.
I found a clean solution for this case to get those pieces on separate files (more simple than any kind of complex template system when you have the views in components instead of having all views on an single path).
In .hbs could be a small dictionary before loading the script with all string values I could need.
<script>
var hello = "{{{lang.hello}}}";
</script>
<script src="viewScript.js"></script>
this method is simple, don't duplicate anything and leaves me to do dynamic names with jquery and a lot of more stuff.

express-handlebars accessing variables declared in the client javascript

I am learning to use handlebars for templates in my website.
I am using node.js so I have used the express-handlebars module as it seems popular and has a lot of support.
I set up some basic config as so..
var exphbs = require('express-handlebars');
app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', exphbs({
defaultLayout: 'layout',
}));
app.set('view engine', 'handlebars');
My understanding is that my views in handlebars (ie my content pages) are templates in handlebars and under the hood I think these templates are being compiled on my behalf so that I can concentrate on using them.
Now, I can pass in data to the template from my node express router and then access and render data in the template using the handlebars notation {{ variable }}.
That's great. But....I want to declare variables on the client using javascript, probably as the result of getting some data back from an Ajax call that I want to enter. Unfortunately this never seems to work. I cannot figure out how I can access a local variable in my template. There is surely a way to do it?
the #with block helper looked promising but unfortunately it didn't do what I expected.
Here is a snippet of one of my content pages with a couple of attempts to declare data locally and render its value.
<div>
<script>let test = {
text: 'this is my example text'
};
</script>
<div>
{{#with test}}
{{text}}
{{/with}}
</div>
<div>
{{test.text}}
</div>
</div>
I have read a lot of articles and watched a lot of videos and I just cannot find anywhere where somebody uses the 'express-handlebars' module and then renders data defined locally.
I am probably missing something obvious but I have been struggling for a while now.
Does anybody have any idea how I can do this please?
thanks in advance.
Okay...it looks like client-side templateing has to be configured separately using webpack. I suppose this makes sense because express handlebars compiles the templates (which just resolves to plain javascript that takes the variables I want to render and wraps in the html needed) and I haven't been able to find any templates on my client through the inspector in the browser. I haven't had chance to try it yet, but this looks promising : http://initialdigital.com/sharing-handlebars-templates-on-both-server-client-in-node-js-express-with-webpack/

How to achieve jade template inherit in node.js

I have two jade template in the same folder,just like:
|__layout.jade
|__content.jade
and the layout.jade is the parent template, the content.jade will inherit from it: so in the layout.jade:
doctype 5
html(lang="en")
head
title= title
body
block content
in the content.jade
extends layout
block content
h1 this is frome nested template
however, when I run it, the inherit doesn't work, it only show the parent template's content
so what't wrong with my code?
Make sure you include the keyword "append" in content.jade.
extends layout
block append content
h1 this is from nested template
More on this here.
This might be a total red herring, but I noticed your two files seem to have inconsistent indentation (at least as pasted in above).
Does it work if you correct this?
I had a similar problem and tried various answers for node.js on stack-overflow/Jade documentation.
In your app.js file check the following..
1) Check that the view engine is set to jade (now renamed pug):
app.set("view engine", "jade");
2) Set the views folder (i.e. where you've saved your template/views files):
app.set("views", __dirname + "/views");
3) Set layout to false:
app.set('view options', { layout: false });
4) If your using express, check that you are rendering the correct file
app.get("/", function(req, res){
res.render("contents.jade");
});
Hope that helps
I tested your code, it is ok, would you like to try a newer version of node.js and jade?

Node.js express: confuse about ejs template

I put my ejs template file in views folder like:
views
|
|--foo.html
|
|--layout.html
so I config my ejs template:
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
I render my foo template by this:
res.render('foo.html', {title: 'test'});
I want use layout.html as the master layout template, I also add <%- body%> tag in layout.html, but is doesn't work, what I saw is only return the ended foo.html.
Why the layout.html can't be the master layout?Or how can I set it to the master layout?
Ahah you just got tricked by Express 3 change in layout management.
The official example: https://github.com/visionmedia/express/tree/master/examples/ejs
Has not been updated.
In Jade you now have to use blocks and extend the layout.
http://www.devthought.com/code/use-jade-blocks-not-layouts/
Try to use ejs-locals then you can do this in a login.ejs file:
<% layout('layout') -%>
<form></form>

Resources