Skip to content

Instantly share code, notes, and snippets.

@joyrexus
Last active January 20, 2024 22:01
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joyrexus/ff9be7a1c3769a84360f to your computer and use it in GitHub Desktop.
Save joyrexus/ff9be7a1c3769a84360f to your computer and use it in GitHub Desktop.
nested templates in go

Example of nested templates.

Given this file layout ...

.
├── server.go
└── templates
    ├── profiles.html
    └── layout.html

... you can run the server (go run server.go).

Running curl localhost:3000/users should then return ...

<html>
  <head>
    <title>User Profiles</title>
  </head>
  <body>
    
  <h2>User Profiles</h2>
  
    <p>
      Jack has the following hobbies ...
      <ul>
        <li>snowboarding</li>
        <li>croquet</li>
      </ul>
    </p>
  
    <p>
      Jill has the following hobbies ...
      <ul>
        <li>knitting</li>
        <li>minecraft</li>
      </ul>
    </p>

  </body>
</html>
<html>
<head>
<title>User Profiles</title>
</head>
<body>
<h2>User Profiles</h2>
<p>
Jack has the following hobbies ...
<ul>
<li>snowboarding</li>
<li>croquet</li>
</ul>
</p>
<p>
Jill has the following hobbies ...
<ul>
<li>knitting</li>
<li>minecraft</li>
</ul>
</p>
</body>
</html>
<html>
<head>
<title>{{ template "title" . }}</title>
</head>
<body>
{{ template "content" . }}
</body>
</html>
{{ define "title" }}{{.Title}}{{ end }}
{{ define "content" }}
<h2>{{.Title}}</h2>
{{range .Profiles}}
<p>
{{ .Name }} has the following hobbies ...
<ul>
{{range .Hobbies}}
<li>{{ . }}</li>
{{end}}
</ul>
</p>
{{end}}
{{ end }}
package main
import (
"html/template"
"net/http"
)
func main() {
http.HandleFunc("/users", users)
http.ListenAndServe(":3000", nil)
}
// user profile
type Profile struct {
Name string
Hobbies []string
}
// user profiles
type Profiles []Profile
// context for templates
type Context struct {
Title string
Profiles Profiles
}
// handler func for `/users`
func users(w http.ResponseWriter, r *http.Request) {
profiles := Profiles{
Profile{"Jack", []string{"snowboarding", "croquet"}},
Profile{"Jill", []string{"knitting", "minecraft"}},
}
context := Context{"User Profiles", profiles}
// layout file must be the first parameter in ParseFiles!
templates, err := template.ParseFiles(
"templates/layout.html",
"templates/profiles.html",
)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := templates.Execute(w, context); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
@smithaitufe
Copy link

What is your layout structure is something like this
LayoutA -> LayoutB -> LayoutC -> PageA?

@g-harel
Copy link

g-harel commented May 23, 2019

This blogpost adds some context for those who want more details.

@joangavelan
Copy link

Great example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment