I would like to write such a conditional fragment in a Go HTML template :
{{if isUserAdmin}}
<a href"/admin/nuke">Go to the big red nuclear button</a>
{{end}}
However, this is not directly possible because the template is not aware of the request that triggered its execution, so it cannot determine if the user is admin or not.
Is there some normal way to achieve this ?
In advance I point out that :
{{if isUserAdmin}}
is not logic itself, it's a necessary construct to leverage a boolean value already calculated by the controller.isUserAdmin()
Here is a working solution attempt (link to Playground) using Funcs to overwrite "isAdmin"
, after template compilation but before each execution (thanks to Valentin CLEMENT in other question).
But it has several flaws :
"isAdmin"
function before template compilation.The normal thing to do is to simply pass your template a struct with whatever static data you like. Unless I've misunderstood what you're trying to do, there doesn't seem to be any need for Funcs
here. Simplifying your example:
package main
import (
"html/template"
"os"
)
const hometmpl = `
{{if .IsAdmin}}
<a href="/admin/nuke">Go to the big red nuclear button</a>
{{end}}
`
var t = template.Must(template.New("home").Parse(hometmpl))
func isAdmin(token string) bool {
const adminToken = "0xCAFEBABE"
return token == adminToken
}
func main() {
token := "0xCAFEBABE" // Or extracted from the http.Request
t.ExecuteTemplate(os.Stdout, "home", struct{IsAdmin bool}{isAdmin(token)})
}
I would agree with Darshan Computing, I think the proper way of passing information from the request would be in the pipeline. You can have your data being split between the data you want to render and the context, e.g. by having your template data structure embed them both if you want to clearly separate the two:
type TemplateData struct {
*Content
*Context
}
Which gives this for example. You can then reuse some of your context/content information depending on what is shared and what is query specific.