DEV Community

Naufal Rabbani
Naufal Rabbani

Posted on

How do I setup templating in Golang Project

Use xtemplate for nested templating

Here the example when I use xtemplate alongside with go-fiber.

Why I use xtemplate if go-fiber already created official html templating with nested feature? This pattern is currently what I'm familiar with. So, for now, I have no issue to keep using it.

But this might not comply with your project needs.

package helpers

import (
    "github.com/dannyvankooten/extemplate"
    "github.com/gofiber/fiber/v2"
)

// Init
var xt = extemplate.New()

// we only need call this once.
func ParseTemplateWithinDir(viewDir string) error {
    return xt.ParseDir(viewDir, []string{".html"})
}

// Render the targeted template
func RenderTemplateWithContext(c *fiber.Ctx, viewDir, name string, data map[string]interface{}) error {

        // In development phase, I want to make it re-parsing the template every time my app render the pages.
        // this is Opt-in. And we can disabled it in production env.
    err := ParseTemplateWithinDir(viewDir)
    if err != nil {
        return err
    }

        // Execute the template.
    return xt.ExecuteTemplate(c.Response().BodyWriter(), name, data)
}

// helper to ensure the response is HTML
func UseHtml(c *fiber.Ctx) {
    c.Response().Header.Add("Content-Type", "text/html; charset=utf-8")
}

Enter fullscreen mode Exit fullscreen mode

Create the templates

File views/base.html

<!-- file: views/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing Unpolly</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly-bootstrap5.min.css">
</head>
<body>
    {{block "content" .}}From Parent{{end}}
    <h1>Another Content!</h1>

    <script src="https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly.min.js"></script>
    <script
            src="https://code.jquery.com/jquery-3.7.1.min.js"
            integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
            crossorigin="anonymous"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

File views/home.html

{{extends "base.html"}}
{{define "content" -}}
<!-- file: views/home.html -->
<h1>From Home template (children)</h1>
{{end}}
Enter fullscreen mode Exit fullscreen mode

Render the Template

Last, render the template.

// handler.go
// ...
app.Get("/app/", func(ctx *fiber.Ctx) error {
    helpers.UseHtml(ctx)
    err := helpers.RenderTemplateWithContext(ctx, ctrl.viewDir, "home.html", map[string]interface{}{
        "someData": "someData to render",
    })
    if err != nil {
        log.Error(err)
    }
    return nil
})
// ...
Enter fullscreen mode Exit fullscreen mode

Done!

Top comments (0)