Skip to content

Instantly share code, notes, and snippets.

@Quaese
Created November 15, 2025 07:41
Show Gist options
  • Select an option

  • Save Quaese/1e76c18356e8b08e9e14d31cc9810b2b to your computer and use it in GitHub Desktop.

Select an option

Save Quaese/1e76c18356e8b08e9e14d31cc9810b2b to your computer and use it in GitHub Desktop.
NodeJS - express-handlebars CheatSheet

Express-Handlebars CheatSheet

Installation

npm install express-handlebars

Grundlegende Einrichtung

Setup in Express

const express = require('express');
const { engine } = require('express-handlebars');

const app = express();

// Handlebars als View Engine registrieren
app.engine('handlebars', engine());
app.set('view engine', 'handlebars');
app.set('views', './views');

Erweiterte Konfiguration

const { engine } = require('express-handlebars');

app.engine('handlebars', engine({
    defaultLayout: 'main',           // Standard-Layout
    layoutsDir: './views/layouts',   // Layout-Verzeichnis
    partialsDir: './views/partials', // Partials-Verzeichnis
    extname: '.handlebars',          // Dateiendung
    helpers: {                       // Custom Helpers
        // Helper-Funktionen hier
    }
}));

Verzeichnisstruktur

views/
├── layouts/
│   └── main.handlebars          # Hauptlayout
├── partials/
│   ├── header.handlebars        # Wiederverwendbare Komponenten
│   └── footer.handlebars
└── home.handlebars              # Views

Layouts

Layout erstellen (views/layouts/main.handlebars)

<!DOCTYPE html>
<html>
<head>
    <title>{{title}}</title>
</head>
<body>
    {{> header}}
    
    {{{body}}}  <!-- View-Inhalt wird hier eingefügt -->
    
    {{> footer}}
</body>
</html>

Layout in Route verwenden

app.get('/', (req, res) => {
    res.render('home', {
        title: 'Startseite',
        layout: 'main'  // Optional, wenn defaultLayout gesetzt
    });
});

Kein Layout verwenden

res.render('home', {
    layout: false  // Rendert ohne Layout
});

Partials

Partial registrieren

app.engine('handlebars', engine({
    partialsDir: [
        'views/partials',
        'views/components'  // Mehrere Verzeichnisse möglich
    ]
}));

Partial verwenden

{{> header}}
{{> components/navigation}}
{{> footer data=footerData}}

Partial mit Kontext

{{> userCard user=currentUser}}

Helpers

Einfache Helpers

app.engine('handlebars', engine({
    helpers: {
        // String in Großbuchstaben
        uppercase: (str) => str.toUpperCase(),
        
        // Datum formatieren
        formatDate: (date) => {
            return new Date(date).toLocaleDateString('de-DE');
        },
        
        // Mathematische Operation
        add: (a, b) => a + b,
        
        // JSON ausgeben
        json: (context) => JSON.stringify(context, null, 2)
    }
}));

Helper in Templates verwenden

<h1>{{uppercase title}}</h1>
<p>Datum: {{formatDate createdAt}}</p>
<p>Summe: {{add 5 10}}</p>
<pre>{{json user}}</pre>

Block Helpers

helpers: {
    // Bedingte Anzeige
    ifEquals: function(arg1, arg2, options) {
        return (arg1 == arg2) ? options.fn(this) : options.inverse(this);
    },
    
    // Liste mit Trenner
    list: function(items, options) {
        const itemsAsHtml = items.map(item => options.fn(item));
        return itemsAsHtml.join(options.hash.separator || ', ');
    }
}

Verwendung:

{{#ifEquals role "admin"}}
    <button>Admin Panel</button>
{{else}}
    <p>Keine Berechtigung</p>
{{/ifEquals}}

{{#list users separator=" | "}}
    {{name}}
{{/list}}

Daten übergeben

Einfache Daten

app.get('/user/:id', (req, res) => {
    res.render('user', {
        title: 'Benutzerprofil',
        user: {
            name: 'Max Mustermann',
            email: 'max@example.com',
            age: 30
        }
    });
});

Template

<h1>{{user.name}}</h1>
<p>Email: {{user.email}}</p>
<p>Alter: {{user.age}}</p>

Eingebaute Handlebars-Features

Variablen

{{title}}                 <!-- Escaped -->
{{{htmlContent}}}        <!-- Unescaped HTML -->

Bedingungen

{{#if isLoggedIn}}
    <p>Willkommen zurück!</p>
{{else}}
    <p>Bitte einloggen</p>
{{/if}}

{{#unless isLoggedIn}}
    <a href="/login">Login</a>
{{/unless}}

Schleifen

{{#each users}}
    <div class="user">
        <h3>{{this.name}}</h3>
        <p>Index: {{@index}}</p>
        <p>Erster: {{@first}}, Letzter: {{@last}}</p>
    </div>
{{else}}
    <p>Keine Benutzer vorhanden</p>
{{/each}}

With Block

{{#with user}}
    <h2>{{name}}</h2>
    <p>{{email}}</p>
{{/with}}

Lookup

{{lookup users userId}}

Konfigurationsoptionen

Option Typ Beschreibung
defaultLayout String Standard-Layout-Name (Standard: 'main')
layoutsDir String Pfad zum Layouts-Verzeichnis
partialsDir String/Array Pfad(e) zu Partials-Verzeichnissen
extname String Dateiendung (Standard: '.handlebars')
helpers Object Custom Helper-Funktionen
compilerOptions Object Handlebars Compiler-Optionen
runtimeOptions Object Handlebars Runtime-Optionen

Erweiterte Beispiele

Runtime Options

app.engine('handlebars', engine({
    runtimeOptions: {
        allowProtoPropertiesByDefault: true,
        allowProtoMethodsByDefault: true
    }
}));

Compiler Options

app.engine('handlebars', engine({
    compilerOptions: {
        strict: true,
        noEscape: false
    }
}));

Custom Extension

const { create } = require('express-handlebars');

const hbs = create({
    extname: '.hbs',
    helpers: {
        section: function(name, options) {
            if (!this._sections) this._sections = {};
            this._sections[name] = options.fn(this);
            return null;
        }
    }
});

app.engine('.hbs', hbs.engine);
app.set('view engine', '.hbs');

Fehlerbehandlung

app.get('/page', (req, res, next) => {
    res.render('page', { data }, (err, html) => {
        if (err) {
            console.error(err);
            return next(err);
        }
        res.send(html);
    });
});

Nützliche Tipps

Partials dynamisch laden

{{> (lookup . 'partialName')}}

Layout-Sections

<!-- In View -->
{{#*inline "sidebar"}}
    <div>Sidebar Inhalt</div>
{{/inline}}

<!-- In Layout -->
{{#block "sidebar"}}
    Standard Sidebar
{{/block}}

Kontext debuggen

{{log this}}
{{log "User object:" user}}

Helper mit diesem Kontext

helpers: {
    fullName: function() {
        return `${this.firstName} ${this.lastName}`;
    }
}

Verwendung:

<p>{{fullName}}</p>

Häufige Patterns

Layout mit Sections

// Layout: main.handlebars
<!DOCTYPE html>
<html>
<head>
    {{{_sections.head}}}
</head>
<body>
    {{{body}}}
    {{{_sections.scripts}}}
</body>
</html>

// View: page.handlebars
{{#section 'head'}}
    <link rel="stylesheet" href="/css/custom.css">
{{/section}}

<h1>Inhalt</h1>

{{#section 'scripts'}}
    <script src="/js/custom.js"></script>
{{/section}}

Daten an Partials übergeben

{{> userCard 
    user=currentUser 
    showEmail=true 
    theme="dark"
}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment