3

Go base lib's template has method Execute which allows to reference another template in order to use template nesting, like follows:

template.Template.Execute("base", data)

Also see this SO question.

How can I achieve the same but inside gin tonic's http response handler? Typically it looks like this

func about(c *gin.Context) {
    c.HTML(http.StatusOK, "about.tmpl", gin.H{})
}

Which leaves no way to reference another template like with execute.

Piotr Zakrzewski
  • 3,591
  • 6
  • 26
  • 28

1 Answers1

0

I had the same problem. From the Gin documentation:

Gin allow by default use only one html.Template. Check a multitemplate render for using features like go 1.6 block template.

Using gin-contrib/multitemplate, as recommended in Gin's docs, we can achieve results similar to the linked SO question:

templates/base.html:

<html>
  <head>{{ template "head.html" .context }}</head>
  <body>{{ template "body.html" .context }}</body>
</html>

templates/head.html:

<title>{{ .title }}</title>

templates/body.html:

{{ .title }}

main.go

package main

import (
    "github.com/gin-contrib/multitemplate"
    "github.com/gin-gonic/gin"
)

// setupRenderer creates a new multitemplate Renderer with templates added.
func setupRenderer() multitemplate.Renderer {
    renderer := multitemplate.NewRenderer()

    renderer.AddFromFiles(
        "myTemplates",
        "templates/base.html",
        "templates/head.html",
        "templates/body.html",
    )

    return renderer
}

// setupRouter initializes a gin Engine, assigns a template renderer, and creates multiple views to return the templates.
func setupRouter() *gin.Engine {
    router := gin.Default()

    router.HTMLRender = setupRenderer()

    router.GET("/", func(ctx *gin.Context) {
        ctx.HTML(200, "myTemplates", gin.H{"context": gin.H{"title": "index"}})
    })
    router.GET("/other", func(ctx *gin.Context) {
        ctx.HTML(200, "myTemplates", gin.H{"context": gin.H{"title": "other"}})
    })

    return router
}

func main() {
    router := setupRouter()
    router.Run(":8080")
}