Add scripts in express-handlebars from view - node.js

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}}

Related

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

Template engine for express 4 supporting Layouts

I'm looking for alternatives to Jade templates in express 4.x because I really don't like Jade's syntax. I'm tending towards EJS, because it's basically just HTML on steroids.
However, one really nice feature of Jade templates is the ability to use layouts. I've found https://www.npmjs.org/package/express-ejs-layouts, but it seems to be made for express 3 and its build is failing :/.
I also found https://www.npmjs.org/package/ejs-mate which is made for express 4.x but it only seems to support a single content block (body).
I would like to have something like this:
layout.something:
<html>
<head>
<% block styles %>
<% block scripts %>
</head>
<body>
<% block body %>
</body>
</html>
index.html:
uses layout "layout.somehing"
scripts:
<script src="my_custom_script.js"></script>
styles:
<link rel="stylesheet ...></link>
body:
<h1>This is my body!</h1>
So that this yields:
<html>
<head>
<link rel="stylesheet ...></link>
<script src="my_custom_script.js"></script>
</head>
<body>
<h1>This is my body!</h1>
</body>
</html>
Does anyone know an engine that is capable of that besides Jade?
You can try express-handlebars, it supports layout and partial views.

meteor real router for multi page apps without JavaScript render

I am new to meteor and I am trying to do multi-page application where http://www.mydomain.com/page1 will result a totally different page from http://www.mydomain.com/page2.
By totally different I mean that I don't want the page to be rendered by the client.
I tried to use meteor-router but What I got is something like:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/myapp.css?9297ad4aa173c4e0c19aebd27c62a5c43242bb93">
<script type="text/javascript">
__meteor_runtime_config__ = {"ROOT_URL":"http://localhost:3000","serverId":"iMp4kgzzeqDtktJoY"};
</script>
<script type="text/javascript" src="/packages/underscore/underscore.js?6d71e6711255f43c0de8090f2c8b9f60534a699b"></script>
<script type="text/javascript" src="/packages/meteor/client_environment.js?07a7cfbe7a2389cf9855c7db833f12202a656c6b"></script>
<script type="text/javascript" src="/packages/meteor/helpers.js?2968aa157e0a16667da224b8aa48edb17fbccf7c"></script>
...
...MANY MANY MANY SCRIPTS.... ?!?
...
...
<script type="text/javascript" src="/myapp.js?2866dcdb5c828b129cdd3b2498a4bf65da9ea43f"></script>
<title>myapp</title>
</head>
<body>
</body>
</html>
And this is not what I want. I want page1 route will return me:
<!DOCTYPE html>
<html>
<head>
My meta tags
</head>
<body>
page1
</body>
</html>
And I want page2 to return different meta tags with different content.
In order to be clear, lets assume that my clients sometime doesn't have javascript. I don't asking about whether meteor is the right framework! I am asking only if can I do this with meteor.
Meteor works a bit different compared to the traditional LAMP stack. Basically it works by patching out the DOM to only where the changes are needed as opposed to re-downloading the whole web page. It makes for a very satisfying end user experience on modern web browsers.
To use meteor router you need to find a spot that you want to patch out with new data for different pages with {{renderPage}}. You can use something like
<head>
<title>xx</title>
</head>
<body>
{{renderPage}}
</body>
<template name="page1">
<h2>Hello!</h2>
</template>
<template name="page2">
<h2>Ola!</h2>
</template>
Now you need to define a router in your client side javascript:
Meteor.Router.add({
'/page1': 'page1',
'/page2': 'page2'
});
So if you load /page1 you would see Hello! and if you load /page2 you would see Ola! as defined in the <template name="page2">..</template>
With the meta tags you need to use javascript to create them. With something like
$('head').append("<meta...");
Again this depends on your preference, personally I find these type of apps load ridiculously fast between web pages as compared to other 'thin' based websites. (Have a look at meteor.com to see how fast you can swap between the pages). The browser does need javascript, however.
Of note is in production mode there will only be 1 script tag.

How to use literal expressions under templates in locomotivejs?

I have the following template:
<!DOCTYPE HTML>
<html>
<head>
<link href="css/style.css" rel="stylesheet"/>
<script type="text/javascript" src="/js/libs-0001.js" async="async"></script>
<script type="text/javascript" src="/js/app-0004.js" async="async"></script>
<script>
var name = {literal}<%= name %>{/literal};
var version = {literal}<%= version %>{/literal}};
</script>
</head><body></body></html>
Like in smarty, from php, I want to use {literal} declarations in the template, under the script session.
How to do this in locomotivejs views?
As far as I understand {literal}/{/literal}, everything between those tags isn't interpreted. EJS templates don't have something similar, although there are ways of circumventing that.
One way is to configure EJS to use different open/close tags, described here.
Another way is to use a different templating engine altogether, which isn't too difficult since LocomotiveJS isn't hardcoded to using EJS templates. I like the Swig templating engine myself, which has the {% raw %} tag that seems to do the same as {literal}.

Express view render using HBS strips (consumes?) Handlebars client side templates

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>

Resources