Reputation: 932
I am a complete beginner to handlebars and am trying to modify the simple handlebars template taken from the example on glitch.com
I would like to be able to link between .hbs
files as I would link between .html
files but when I try however I am given the message cannot GET
followed by whatever file I give to it.
Here is a grab of my overall structure for ref;
Here is the index.hbs
files I am working with
<!DOCTYPE html>
<html>
{{> head }}
<body>
<a href="views/secondpage.hbs">Link to second page</a>
</body>
</html>
Which I would like to link to (for example) this secondpage.hbs
file;
<!DOCTYPE html>
<html>
{{> head }}
<body>
<a href="views/index.hbs">Link back to index</a>
</body>
</html>
Here is the code in my server.js
file
// Generic node.js express init:
const express = require('express');
const app = express();
app.use(express.static('public'));
const hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials/');
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');
app.get("/", (request, response) => {
let dt = new Date();
let data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random()*1000),
serverTime: new Date(),
ip: (request.headers["x-forwarded-for"]||"").split(",")[0]
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
let listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
and the code in my watch.json
{
"install": {
"include": [
"^package\\.json$",
"^\\.env$"
]
},
"restart": {
"exclude": [
"^public/",
"^dist/"
],
"include": [
"\\.js$",
"\\.hbs$",
"\\.json"
]
},
"throttle": 100
}
If any of the details of the other files is necessary to assist let me know and I can provide.
I appreciate I am probably thinking about this in the wrong way, I have looked at handlebars in more detail and experimented with helpers etc. but it seems overly complicated for what I am trying to achieve, I thought you could write basic html
within an hbs
file? I am looking for the most straightforward, generic solution to the problem of linking between views in handlebars.
FWIW I want to use handlebars in a pretty simple fashion, basically just looking to have the equivalent of php includes
using partials
instead, so if there is a better way to approach the creation of the app with that in mind I would be grateful for advice.
Upvotes: 1
Views: 13234
Reputation: 11
Instead of using handlebars I used express-handlebars Terminal: npm i express-handlebars
Handlebars is a Middleware and functions as a Twig (Template Engine) so for your server I'd suggest:
// Generic node.js express init:
const express = require('express');
const app = express();
app.use(express.static('public'));
const exphbs = require('express-handlebars');
app.set('views', __dirname + '/views');
// added this part
app.engine('.hbs', exphbs ({
defaultLayout: 'main',
layoutsDir: ('views', __dirname + 'layouts'),
partialsDir: ('views', __dirname 'partials'),
extname: '.hbs'
}));
app.set('view engine', 'hbs')
app.get("/", (request, response) => {
let dt = new Date();
let data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random()*1000),
serverTime: new Date(),
ip: (request.headers["x-forwarded-for"]||"").split(",")[0]
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
let listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
By doing this, you should have a file in your layouts folder named main.hbs where you will have that dynamic approach you're looking for. Something that stays the same for all pages. I will insert here a suggestion, feel free to adapt for your code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- CUSTOM CSS -->
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
{{> navigation }}
<main class="container p-5">
{{{ body }}}
</main>
</body>
</html>
Now when you create a navigation.hbs
in your partials folder you will have the same frontend in all pages in the navigation. This is because we defined in the server.js
our default template to be main.hbs
. Whilst for your body, the triple hash ({{{}}}
) inserts the components of the other .hbs files that you define. Don't forget to create a index.hbs
file inside the views folder.
I learned the basics of hbs by following this tutorial (Note it's in Spanish). The tutorial produces this open-source project (which I am including in case it is useful).
Upvotes: 0
Reputation: 6570
Your code looks alright. What is the problem exactly? When you add {{> head}}
partial to the index.hbs
doesn't it render properly?
EDIT:
Okay, you have mainly 2 problems with your code:
express
linking to your /secondpage
endpoint. <a href="views/secondpage.hbs">Link</a>
instead of linking to an URL endpoint <a href="/secondpage">Link</a>
.To fix your code you would have to define the endpoint linking to the handlebars
file, so you need to change your server.js
file to something like this.
const express = require('express');
const hbs = require('hbs');
const app = express();
app.use(express.static('public'));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');
hbs.registerPartials(__dirname + '/views/partials/');
// 1st Page Route (URL Endpoint)
app.get('/', (request, response) => {
const data = {
projectName: process.env.PROJECT_DOMAIN,
luckyNumber: Math.floor(Math.random() * 1000),
serverTime: new Date(),
ip: (request.headers['x-forwarded-for'] || '').split(',')[0],
};
data.json = JSON.stringify(data, null, 2);
response.render('index', data);
});
// 2nd Page Route (URL Endpoint)
app.get('/secondpage', (request, response) => {
response.render('secondpage');
});
const listener = app.listen(process.env.PORT, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
And then you need to fix your HTML links to this on index.hbs
:
<!DOCTYPE html>
<html>
{{> head }}
<body>
<a href="/secondpage">Link to second page</a>
</body>
</html>
And this on secondpage.hbs
:
<!DOCTYPE html>
<html>
{{> head }}
<body>
<a href="/">Link back to index</a>
</body>
</html>
Hope this helps you.
Upvotes: 4