Search code examples
gotemplatesmiddlewarego-gin

Golang Gin Middleware pass Data to Template


Hi currently i am doing a little project and i have question.

Is there a way to pass Data to a template from a Middleware?

For Example:

func CheckAuth(c *gin.Context) { //This Middleware gets the user from the session and passes it to the template 
session := sessions.Default(c)
user := session.Get(userkey)

// Get if possible the user from the database with id = user
var account models.Account
if err := models.DB.Where("id = ?", user).First(&account).Error; err != nil {

    _ = 1
}
// pass the account into every temaplte

c.Next()

The reason is that i use the user in my layout and have to check his username or if he is just nil etc and doing the pass in every functions feels wrong? I know Laravel has something like this.

I am using the c.HTML to display the html file

Thanks in advance!


Solution

  • You can use SetFuncMap or FuncMap to create custom functions on templates.

    You must set it before calling LoadHTMLFiles or LoadHTMLGlob.

    Middleware is for control value, ie: struct

    This is the example

    main.go

    package main
    
    import (
        "html/template"
        "log"
        "strconv"
    
        "github.com/gin-gonic/gin"
    )
    
    type User struct {
        Username string
    
        Age int
    }
    
    func setUser(u *User) gin.HandlerFunc {
        return func(ctx *gin.Context) {
            // u.Age = 100
            // u.Username = "Default"
            if s, b := ctx.GetQuery("username"); b {
                u.Username = s
            }
            if s, b := ctx.GetQuery("age"); b {
                i, err := strconv.Atoi(s)
                if err != nil {
                    panic(err.Error())
                }
                u.Age = i
            }
        }
    }
    
    var user = &User{"Default", 100}
    
    func GetUsername() string {
        return user.Username
    }
    
    func GetAge() int {
        return user.Age
    }
    
    func main() {
        r := gin.New()
    
        r.SetFuncMap(template.FuncMap{
            "Username": GetUsername,
            "Age":      GetAge,
        })
        r.LoadHTMLGlob("*.tmpl")
    
        r.GET("/", setUser(user), func(ctx *gin.Context) {
            data := map[string]interface{}{
                "title": "Learning Golang Web",
                "name":  "Batman",
            }
    
            ctx.HTML(200, "index.tmpl", data)
        })
    
        log.Fatalln(r.Run())
    }
    

    index.tmpl

    <!DOCTYPE html>
    <html>
      <head>
        <title>{{.title}}</title>
      </head>
      <body>
        <p>Welcome {{.name}}</p>
        <p>Your Username is {{ Username }}</p>
        <p>Your Age is {{ Age }}</p>
      </body>
    </html>
    

    if you go to http://localhost:8080/?username=admin&age=50 it will show different display