2

I am building a front end website with Golang Echo Labstack framework, and I want to call some custom functions in my template view. How do I do this with Echo?

For example, I am able to do this with Gin

func main() {
    r := gin.Default()
    r.SetFuncMap(template.FuncMap{
        // Add my custom functions
        "AddTS": util.AddTS,
        "Encrypt": util.EncryptGeneral,
        "CombineVariable": util.CombineVariable,
    })
    
    r.Static("/static", "./static")
    r.LoadHTMLFiles("static/*/*") //  load the static path
    r.LoadHTMLGlob("templates/*/*")

    route.Routes(r)
    r.Run()
}

and in my template view, I could simply call any of my custom functions like this.

range {{ .Data }}
    <div>
        {{ .data_value | AddTS }}
        {{ .data_value | OtherCustomFunction }}
    </div>
{{ end }}

But I can't seem to find a similar methods in Echo, how do I implement a global function that I can use in my template views?

Here is my current Echo file

type TemplateRenderer struct {
    templates *template.Template
}

func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {

    // Add global methods if data is a map
    if viewContext, isMap := data.(map[string]interface{}); isMap {
        viewContext["reverse"] = c.Echo().Reverse
    }

    return t.templates.ExecuteTemplate(w, name, data)
}

func main() {
    e := echo.New()

    renderer := &TemplateRenderer{
        templates: template.Must(template.ParseGlob("templates/*/*.tmpl")),
    }
    e.Renderer = renderer

    e.Static("/static", "static")
    
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Logger.Fatal(e.Start(":8183"))
}

*For some reasons, I cannot use Gin for this project and must only use Echo.

Thanks a lot.

Charas
  • 1,753
  • 4
  • 21
  • 53
  • https://echo.labstack.com/guide/templates/ – mkopriva Jul 10 '22 at 16:13
  • hello, yes I have read the docs multiple times and implemented it but could not seem to get it to work, I'm sorry I'm a newbie, where should I put the function codes? *I have added my current code – Charas Jul 10 '22 at 16:21
  • In your `main` in `template.Must` do `template.New("t").Funcs(template.FuncMap{...}).ParseGlob(...)`, see: https://pkg.go.dev/html/template@go1.18.3#Template.Funcs – mkopriva Jul 10 '22 at 16:23
  • If the above suggestion fails and you can't figure out why then update your question to show the new code and also add information about the error, like what is the *exact* error message, which like is the error coming from, etc. – mkopriva Jul 10 '22 at 16:26
  • It works! Thank you very much sir. I am really still getting the hang of this template things, please put it as an answer so I could accept it as an answer and may help others that find a similar problem. – Charas Jul 10 '22 at 16:31

1 Answers1

3

You can easily implement your own renderer, as explained in the guide here, and use Go's own html/template package to manage the templates:

import (
    "html/template"
    // ...
)

type TemplateRenderer struct {
    templates *template.Template
}

func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {

    // Add global methods if data is a map
    if viewContext, isMap := data.(map[string]interface{}); isMap {
        viewContext["reverse"] = c.Echo().Reverse
    }

    return t.templates.ExecuteTemplate(w, name, data)
}

And to give the templates access to custom functions you can use the Funcs method like so:

renderer := &TemplateRenderer{
    templates: template.Must(template.New("t").Funcs(template.FuncMap{
        "AddTS":           util.AddTS,
        "Encrypt":         util.EncryptGeneral,
        "CombineVariable": util.CombineVariable,
    }).ParseGlob("templates/*/*.tmpl")),
}
mkopriva
  • 35,176
  • 4
  • 57
  • 71