最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the simplest way to link between .hbs files using handlebars? - Stack Overflow

programmeradmin1浏览0评论

I am a plete beginner to handlebars and am trying to modify the simple handlebars template taken from the example on glitch

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 plicated 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.

I am a plete beginner to handlebars and am trying to modify the simple handlebars template taken from the example on glitch.

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 plicated 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.

Share Improve this question asked Jun 30, 2019 at 21:20 NickNick 9322 gold badges12 silver badges34 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

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:

  • You have no route defined on express linking to your /secondpage endpoint.
  • You are trying to link to a file <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.

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 ponents 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).

发布评论

评论列表(0)

  1. 暂无评论