express-handlebars accessing variables declared in the client javascript - node.js

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/

Related

Why res.render() doesn't send local variables to the client without template engine?

I need to access the variable user in my client-side that sent by
res.render('home.html', { user: req.user });
without using template engines like pug or ejs
Is that possible?
HTML is not a templating language, so it can't be used to send variables.
res.render() function compiles your template , inserts locals there, and creates html output out of those two things. The syntax is as follows -
res.render(view [, locals] [, callback])
The view argument is a string that is the file path of the view file to render. For this to work, you need a template or view engine .
In html, you can't dynamically pass/insert data variables. That's the main use case for templating engine. They put runtime/dynamic value in html which is what you are probably looking for.
In short, its better to use any template engine like pug,jade,ejs, etc most of which would have almost similar syntax with html to render dynamic html pages. I don't think there's any method (atleast simple enough) to send variables dynamically from server to client in an html page. Using a template engine would be the best choice in your use case.
For eg. you are passing user from server side and most probably want the passed variable to be rendered on the client side. You can just install an view engine like ejs - npm install ejs, set your view engine in app.js - app.use('view engine','ejs'); , and just add this line in the html page where you want to send the variable to client side like - <p> <%= user %> </p> and that's it. Keep your html file in view folder and this would do it.

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.

How do you render when organising project by feature?

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.

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.

Why do you need a templating language with Node.js?

After doing some research, everyone seems to advise learning and using some form of a templating language with node.js. Why? Couldn't you just use HTML, and if so, how? I'm new to Node, so I downloaded Express and immediately I asked myself, "What is .jade?"
There is no requirement, but it can be much nicer. You can just as easily manually output HTML, but then you are forced to keep all of your HTML inside of JS strings at all times, or keep it in a file.
You'd do something like this:
res.send("<html><body>" + content + "</body></html>");
As soon as you want to have dynamic HTML, you either need to include it directly in your code, or you need to have it in a template. The difficulty is that you can't just throw standard HTML in a file, because that essentially makes it impossible to dynamically alter the page. To solve this problem, usually you'd dynamically generate HTML using some kind of templating language like jade.
For a tiny one-off app, it may not be a big deal, but separating your presentation HTML from your code becomes very important as the size of the app you are developing grows.
If your're using express use the code below
var express = require('express');
var app = express.createServer(
express.static(__dirname + '/public')
);
app.listen(3000);
Then put all your html files in the /public folder. That's it.

Resources