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")
}
Create the templates
File views/base.html
</span>
lang="en">
charset="UTF-8">
Testing Unpolly
rel="stylesheet" href="https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly.min.css">
rel="stylesheet" href="https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly-bootstrap5.min.css">
{{block "content" .}}From Parent{{end}}
Another Content!
"https://cdn.jsdelivr.net/npm/unpoly@3.11.0/unpoly.min.js">
"https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous">
File views/home.html
{{extends "base.html"}}
{{define "content" -}}
From Home template (children)
{{end}}
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
})
// ...
Done!