Template engine for express 4 supporting Layouts - node.js

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.

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

Adding extra scripts and headers to ufront-erazor html layout

Using ufront and erazor I ran into the following problem very quickly.
The hello-world example provides the following layout:
<!DOCTYPE html>
<html lang="en">
<head>
<title>#title</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
#viewContent
</div>
</body>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"</script>
</html>
For certain pages I want to add more headers or scripts after Jquery has been loaded.
One way to do so (for the scripts for example), would be to pass the scripts as an array of strings, and construct them on the layout file :
...
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"</script>
#for(script in scripts) {
<script src='#script.path'></script>
}
</html>
....
The problem with this approach is that I can't keep meaningful headers + body + scripts on the same template file witch would be great, also needs extra care to pass the scripts and headers as context.
Some template engines like Razor or Laravel allow to do that using 'sections'.
Is it possible to do something similar with erazor? If not what would be a good alternative?

Jade not correctly rendering elements with ng-view directive

I'm writing a basic Node app and simply want to render the index page with Jade, and then let Angular do the rest on the front-end.
This is the Jade (slightly shortened to illustrate the problem):
doctype html
html
include ../includes/head
body(ng-app="TestApp" ng-controller="TestAppController")
div(ng-view)
include ../includes/foot
Which compiles to the following HTML:
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
<link rel="stylesheet" href="/dist/css/app.css">
</head>
<body ng-app="ExampleApp" ng-controller="ExampleAppController" class="ng-scope">
<!-- ngView: -->
<footer class="page-footer">
<ul class="page-footer-links">
<li>Some Twitter User</li>
</ul>
</footer>
<script src="/dist/js/app.min.js"></script>
</body>
</html>
Notice how div(ng-view) is now an HTML comment within the rendered HTML, rather than a DIV with the directive:
<!-- ngView: -->
Changing div(ng-view) within the Jade to any of the following produced the same result for me:
ng-view
<div ng-view></div>
| <div ng-view></div>
Any ideas as to why this is happening?
This was actually nothing to do with Jade. As stated in a comment by #NikosParaskevopoulos, the <!-- ngView: --> HTML comment is a placeholder created by Angular upon seeing a <div ng-view> and having no route to display in it.
Redefining my Angular routes solved the problem.

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.

node.js jshtml-express layout

Hello!
Is there any way to have the master page or layout in jshtml?
I tried do this in .net Razor style, but it did't works.
Link to jshtml view engine.
My intention is to have mastarpage lets say is called layout.jshtml and some other subpages like index.jshtml and so on, like it is in razor.
More explanation of what I mean speaking "I would like have masterpage"
I have Layout.jshtml , this is my masterpage
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css" ></link>
</head>
<body>
#writeBody();
</body>
</html>
and I have other view called some.jshtml
<h1>#locals.title</h1>
<div class="Mydata">
#locals.content
#locals.otherContent
</div>
When I run this page in browser I would like to have concatenation of layout.jshtml and some.jshtml. The content of some.jshtml is rendered in writeBody(); in layout.jshtml
When I speaking of concatenation I mean someThing like this. This is result that I can see in browser.
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css" ></link>
</head>
<body>
<h1>title</h1>
<div class="Mydata">
content
otherContent
</div>
</body>
</html>
The jshtml repo links to the jshtml-express project.
The docs there give an example of how to use this in your project :
var express = require('express');
var port = parseInt(process.argv.pop());
var app = express();
app.configure(function() {
app.use(express.bodyParser());
app.use(app.router);
});
app.engine('jshtml', require('jshtml-express')); // make sure you have installed via npm install jshtml-express
app.set('view engine', 'jshtml');
I have not used this myself, but the process is similar with other templating systems (Jade, Handlebars, etc).
More explanation of what I mean speaking "I would like have masterpage"
I have Layout.jshtml , this is my masterpage
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css" ></link>
</head>
<body>
#writeBody();
</body>
</html>
and I have other view called some.jshtml
<h1>#locals.title</h1>
<div class="Mydata">
#locals.content
#locals.otherContent
</div>
When I run this page in browser I would like to have concatenation of layout.jshtml and some.jshtml. The content of some.jshtml is rendered in writeBody(); in layout.jshtml
When I speaking of concatenation I mean someThing like this. This is result that I can see in browser.
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css" ></link>
</head>
<body>
<h1>title</h1>
<div class="Mydata">
content
otherContent
</div>
</body>
</html>

Resources