Why does my Go templates always render the last child template when using template inheritance?

1 week ago 5
ARTICLE AD BOX

I'm having an issue using template inheritance in go, but all of my routes are rendering the same file from my templates folder, which happens to be my last one (ViewGames.hmtl). Here is what my templates folder looks like

templates/ partials/ Base.html CreateGame.html LogIn.html AddPlayer.html TeamMode.html ViewGames.html //This one always get rendered.

All of my child templates are inheriting from Base.html, which looks like this:

{{ define "Base" }} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="shortcut icon" href="../static/img/sb_3.png" type="image/x-icon"> <title>{{ template "title" . }}</title> {{ template "css" }} </head> <body> {{ template "content" . }} </body> </html> {{ end }}

Each child template element follows the following format:

{{ define "title" }}Create Game{{ end }} {{ define "css" }} <link rel="stylesheet" href="/static/css/CreateGame.css"> {{ end }} {{ define "content" }} <h1>Create game</h1> {{ end }}

For my backend, I am using Go + chi in the following manner. Templates are parsed once on startup rather than for each request for performance reasons.

type ViewsController struct{ Router *chi.Mux pagesTemplate *template.Template } func (v *ViewsController) Init(){ v.Router = chi.NewRouter() v.pagesTemplate = template.Must(template.ParseGlob("templates/*.html")) v.Router.Get("/", v.CreateGame) v.Router.Get("/team-mode", v.TeamMode) v.Router.Get("/add-player", v.AddPlayer) v.Router.Get("/view-games", v.ViewGames) v.Router.Get("/log-in", v.LogIn) v.Router.NotFound(v.NotFound) }

Each handler has the same format, executing the Base template. In order for the child template to inherit from the base tmeplate, the Base must be called.

func (v *ViewsController) CreateGame(res http.ResponseWriter, req *http.Request){ if err := v.pagesTemplate.ExecuteTemplate(res, "Base", nil); err != nil{ http.Error(res, err.Error(), http.StatusInternalServerError) } }

What Happens

Every single route when hit, will always return ViewGames.html no matter what. It also happens to be the last file in my templates folder alphabetically, which is interesting.

What I Expect

When each route is hit, I expect to them to serve the specific html template for that route, with the CreateGame Handler returning CreateGame.html, TeamMode handler returning TeamMode.html, and so on.

What I've Tried

I've tried calling the Child template for each route that I want served instead of the base template, but the server returns nothing. I've tried parsing each child template in each route like so:

t, _ := template.ParseFiles("templates/Base.html", "templates/CreateGame.html")

but as mentioned before, this is expensive, and much slower, and also results in each route having their own copy of a navbar, which is undesirable.

Question

Why does Go always use the last child template's block definitions, and how do I correctly use template inheritance so each route renders its own child template, while ensuring they all use the same exact Base template?

Read Entire Article