Express view render using HBS strips (consumes?) Handlebars client side templates - node.js

Using Express with Don Park's HBS as the view engine, with the intention of using the same templating style for both client and server code. However I have run into a bit of a snag.
With the index.hbs shown here,
<h1>{{title}}</h1>
<p>Welcome to {{title}}</p>
<div id="place"></div>
<script id="firstTemplate" type="text/x-handlebars-template">
<ul>
{{#lines}}
<li>{{name}}</li>
{{/lines}}
</ul>
</script>
Heres what renders to the browser:
<h1>Express</h1>
<p>Welcome to Express</p>
<div id="place"></div>
<script id="firstTemplate" type="text/x-handlebars-template">
<ul>
</ul>
</script>
The Express View render process seems to have consumed the template block intended for use in the browser. As far as I can tell, the view renderer just takes the entire file.hbs as a string tempate to render, not distinguishing the script block from server view.
Any ideas/workarounds for this?

I'm using Handlebars in the same way and ran into the same problem.
I worked around it by storing this part:
<script id="firstTemplate" type="text/x-handlebars-template">
<ul>
{{#lines}}
<li>{{name}}</li>
{{/lines}}
</ul>
</script>
In a separate static file and then loading it via ajax after the page has rendered. This way my client-side template doesn't get mistakenly rendered by Express.
It would be nice though if there were a way to add a tag to let Express know to ignore blocks like that and leave them for the client-side.

If handlebars is truly compatible with Mustache, then this should work:
Change your delimiter first by putting this somewhere at the top of your template ( before any template placeholders )
{{=<% %>=}}
So now anything you want rendered by the server you will do:
<% foo %>
And anything you want rendered on the client like so:
{{ bar }}
More info is at the bottom of the Mustache manual here - http://mustache.github.com/mustache.5.html

For handlebars, uou can use backslash to escape the double braces, like so:
<script id="firstTemplate" type="text/x-handlebars-template">
<ul>
\{{#lines}}
<li>\{{name}}</li>
\{{/lines}}
</ul>
</script>

Related

How can I include a seperate CSS file from an ejs that borrows from a layout.ejs file?

I have a layout.ejs file that provides the basic layout of every page that I have for my node application. This includes some basic CSS files (i.e bootstrap). I have other ejs files that have their body rendered using that layout.ejs file but I also want them to be able to include their own CSS files for some custom styles.
I've tried to include the CSS directly in the other ejs files but that just sets the css file in the body of the html. I have thought about using a javascript file that injects the CSS file client-side but this feels too 'hacky' for me.
Currently, my test layout (the one that inherits from layout.ejs) looks essentially like this:
<head>
<link href="../public/styles/index.css" rel="stylesheet" type="text\css">
</head>
<section id="box-section" class="blox-mf route">
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="title-box text-center">
<h3 class="title-a">
Title2
</h3>
<p class="subtitle-a" style="color: #be3131;">
Subtitle 2
</p>
<div class="line-mf"></div>
</div>
</div>
</div>
</div>
</section>
<script src="/scripts/index.js" crossorigin="anonymous"></script>
As I said, all I have is a css attached to the body of the html and not in the header so everything keeps the default style as the layout.ejs file. Is there a way I can achieve this by finding a way to get different routes to use the basic layout css files but allow for some variation using their own css?
I found a method to do this. All it takes is to have a variable passed into the template ejs that is an array of URIs to your css files. The ejs then loops through the array and creates the template with the required css files.
Here's the code for passing through the css files:
myCss.push({
uri: 'public/styles/index.css'
})
res.render('./home', {
styles: myCss,
});
And then on the template, all you have to do is:
<% for(var i=0; i < styles.length; i++) { %>
<link href="<%= styles[i].uri %>" rel="stylesheet" type="text/css">
<% } %>
Now all the sheets you need for a route can be passed on. A bit of code refactoring is necessary to replace having to add the links manually but you can get the essence of it.
EDIT:
This requires some setup to serve static files. You can do this by including this in your express application:
app.use(express.static(__dirname + '/public'));

Using nodejs and handlebars

Hi everybody I'm kind new in nodejs problems I hope o can found what I need as simple as possible
So my base problem is how can I use multiple handlebars files in one handlebar page as sections
Like to have a page for the headear and another for the body and others for footer and all that just by using nodejs and handlebars ... And thanks after all ^^
You can define the pages except main page as partials. Then you the files in your main file in the form of {{> filename}}
for eg:
views/
main.handelbars
partials/
-header.handelbars
-body.handelbars
-footer.handelbars
main.handlebars
<html>
<title>xxxxxx</title>
<head>
.....
</head>
{{> header}}
{{> body}}
{{> footer}}
</html>
header.handlebars
<header>
........
</header>
body.handlebars
<div>
........
</div>
footer.handlebars
<footer>
........
</footer>
Dont't forget to add the view engine and mention the public directory to views as well as the partials directory.

Add scripts in express-handlebars from view

I am using Express-Handlebars as my templating engine and I use a layout for all my views. However, I want to be able to add scripts via the view for specific pages. Very much like in this example: is there a way to add CSS/JS later using EJS with nodejs/express
I want to add my scripts after the standard scripts that are used for all pages(bootstrap, jquery). These are placed at the bottom of body in my layout, like so:
<html>
<header>
...
</header>
<body>
...
{{{body}}}
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>
How would I go about doing this using Handlebars? Or is my best bet to use EJS? Or can I use both?
Any help is much appreciated,
Freece
Never mind! I realized that that method would contradict the foundations of Handlebars. Instead I added the following to my controller:
var scripts = [{ script: '/js/myTestScript.js' }];
...
res.render('contact', { title: 'Kontakt', scripts: scripts });
And in my layout it looks like this:
...
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
{{#each scripts}}
<script src="{{script}}"></script>
{{/each}}

Embedded JavaScript (EJS) - Dynamically setting view from route

I'm learning nodejs at the moment and my .ejs template files are pretty much standard (header, footer, js-defaults etc) - and the only thing that changes it the content in a HTML div.
I thought I could set a variable in my route and pass it along to the view (like you would a title or another variable), then include it - but it's not working (example below).
In Ruby you can do this with "yield" and I am trying to do the same with EJS.
Thanks for taking the time to read (and please forgive my ignorance in this matter).
Example Route
app.get('/fish', function(req, res) {
res.render('fish' {
title:"Fish",
template:"view/partials/content/fish.ejs"
});
});
Example EJS
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<% include views/partials/template/header.ejs %>
<body>
<div class="container">
<!-- Dynamic content here -->
<% include template %> <!-- tries to load template.ejs %>
</div>
</body>
<% include views/partials/template/footer.ejs %>
<% include views/partials/template/js-defaults.ejs %>
</html>
Looks like this is now supported in EJS. It was introduced in v2.0.1: 2015-01-02. The new syntax looks like this
<!-- Dynamic content here -->
<%- include(template) %>
To get this to work I had to disable caching in Express by setting:
app.set('view cache', false);

How do I switch partials with Node JS and Sails JS?

I have a 'My Scores' view in my Node JS / Sails JS app and I'm using partials, one for a List View, and another one for a Grid View. When the user clicks the Grid or List View from the nav bar I'd like to be able to swap the UI with the given partial.
List view:
<div class="content-container">
<h1>My Scores</h1>
<%- partial('../partials/list-view')%>
</div>
Grid view:
<div class="content-container">
<h1>My Scores</h1>
<%- partial('../partials/grid-view')%>
</div>
Please advise.
No problem--just use a variable for the partial name, instead of hardcoding it:
<%- partial(viewName) %>
then in your config/routes.js:
"/listView": {
view: "list.ejs",
locals: {viewName: "../partials/list-view.ejs"}
},
"/gridView": {
view: "list.ejs",
locals: {viewName: "../partials/grid-view.ejs"}
}
That's assuming you're just routing directly to views. If you're using a custom controller action and res.view() to display your content, you'll put the viewName value in the second res.view() argument, like res.view("list.ejs",{viewName: "../partials/list-view.ejs"}).
Now, if you're trying to do this without reloading the page, then #tonejac has the right idea in his comment--either switch them using Javascript/CSS, or use AJAX to load content on-demand. Sails can only help on the backend!

Resources