Express.js hbs module - register partials from .hbs file

38,667

Solution 1

This code loads all the partial templates in a directory and makes them available by filename:

var hbs = require('hbs');
var fs = require('fs');

var partialsDir = __dirname + '/../views/partials';

var filenames = fs.readdirSync(partialsDir);

filenames.forEach(function (filename) {
  var matches = /^([^.]+).hbs$/.exec(filename);
  if (!matches) {
    return;
  }
  var name = matches[1];
  var template = fs.readFileSync(partialsDir + '/' + filename, 'utf8');
  hbs.registerPartial(name, template);
});

Solution 2

For convenience, registerPartials provides a quick way to load all partials from a specific directory:

var hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials');

Partials that are loaded from a directory are named based on their filename, where spaces and hyphens are replaced with an underscore character:

template.html      -> {{> template}}
template 2.html    -> {{> template_2}}
login view.hbs     -> {{> login_view}}
template-file.html -> {{> template_file}}

Cheers!

Solution 3

Looks like creating a variable and pulling in the template code manually works:

var hbs = require('hbs')
  , fs = require('fs')
  , headerTemplate = fs.readFileSync(__dirname + '/views/_header.hbs', 'utf8');

and later:

hbs.registerPartial('headPartial', headerTemplate); 

Solution 4

For me I had template file my-partial.hbs

Then I tried to access them via:

{{> my-partial }}

But the partial was stored in hbs as my_partial regardless of the filename.

This is thanks to hbs version 3.1.0 line 218

.slice(0, -(ext.length)).replace(/[ -]/g, '_').replace('\\', '/');

This is in the readme

Solution 5

For me, I have a function like:

var hbs = require('hbs');
var fs = require('fs');    
var statupfunc = {
      registerHbsPartials : function(){
        //this is run when app start
        hbs.registerPartials(__dirname + "/" + resource.src.views + '/partials');        
      },
      registerOneHbsPartials : function(event){ 
        //this is run for gulp watch
        if(event.type == 'deleted')
        {
          return;
        }   
        var filename = event.path;
        var matches = /^.*\\(.+?)\.hbs$/.exec(filename);
        if (!matches) {
          return;
        }    
        var name = matches[1];    
        var template = fs.readFileSync(filename, 'utf8');    
        hbs.registerPartial(name, template);    
      }
    };

Run statupfunc.registerHbsPartials at app startup and then register gulp watch with statupfunc.registerOneHbsPartials to register partials on new creation

gulp.task('watch', function() {
    gulp.watch(resource.src.views +  '/partials/*.*', statupfunc.registerOneHbsPartials);
});
Share:
38,667
swatkins
Author by

swatkins

Interactive Web Developer at Museum of the Bible

Updated on July 18, 2022

Comments

  • swatkins
    swatkins almost 2 years

    I'm using the handlebars.js hbs wrapper in express.js. I have templates working fine, but I'm needing to add in partials to be rendered with my views.

    I'd like to do something like this:

    hbs.registerPartial('headPartial', 'header'); 
    // where "header" is an .hbs file in my views folder
    

    However, it's throwing a "header partial can not be found".

    I can make the registerPartial work if I pass a string of html to the second param, but I'd like to use separate view files for my partials.

    I haven't found any documentation on this, but hoping I may just be missing something easy.

    Does anyone know how to use view files in the registerPartial method? If so, how do I implement this?

    UPDATE

    To give more context, let me add more code. Here is my "server" file - app.js

    var express = require('express')
    , routes = require('./routes')
    , hbs = require('hbs');
    
    var app = module.exports = express.createServer();
    
    // Configuration
    
    app.configure(function(){
      app.set('views', __dirname + '/views');
      app.set('view engine', 'hbs');
      app.use(express.bodyParser());
      app.use(express.methodOverride());
      app.use(app.router);
      app.use(express.static(__dirname + '/public'));
    });
    
    app.configure('development', function(){
      app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    });
    
    app.configure('production', function(){
      app.use(express.errorHandler());
    });
    
    // this is the line that generates the error
    hbs.registerPartial('headPartial', 'header'); 
    
    // What I'm expecting is for "headPartial" to be a compiled template partial 
    // of the template within views/header.hbs, but it is not loading this way.
    // If I do something like hbs.registerPartial('headPartial', '<p>test</p>');
    // then it does work. I need to know how to pass an .hbs file to the
    // registerPartial method.
    
    // Routes
    app.get('/', routes.index);
    
    app.listen(3000);
    

    And here is my routes.index file:

    exports.index = function(req, res){
      res.render('index', { title: 'Express' })
    };
    

    In my views folder, I have three templates:

    views/
      header.hbs (this is my partial)
      index.hbs
      layout.hbs
    

    In my index.hbs file, I'm calling the 'headPartial' partial with:

    {{> headPartial}}
    

    Any help is greatly appreciated.