Reputation: 1680
I am writing a web application in GoLang, not using any framework.
I am trying to create a layout
similar to layouts in nodejs, for example.
=== layout.html ====
{{ define "layout"}}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<link href="/static/style.css" rel="stylesheet" media="all" type="text/css">
</head>
<body>
{{ template "content"}}
</body>
</html>
{{ end }}
I then have my some content in say home.html
{{ define "content"}}
<h1>{{.Title}}</h1>
<div>This is a test</div>
{{ end }}
I have 2 problems with this approach
(1) my Execute template code, does not seem to be passing the data to the content
templates.ExecuteTemplate(w, "layout", &Page{Title: "Home", Body: nil})
(2) If I want to have multiple pages with the same layout, the above will not work as it does not specify which content to load.
Can someone please explain a strategy for using tempates and 'layouts' in GoLang ?
Upvotes: 1
Views: 1841
Reputation: 36199
(1) my Execute template code, does not seem to be passing the data to the content
As people have noted in the comments, you need to explicitly call the template with the data:
{{ template "content" . }}
Notice the dot after the "content"
part.
(2) If I want to have multiple pages with the same layout, the above will not work as it does not specify which content to load.
There are a few ways you can solve this. What I do is this. I don't {{ define "content" }}
in every template. Instead I parse all templates into one:
tmpls, err := template.ParseGlob(tmplGlob)
And then for each request I clone the layout and set the desired template to "content"
:
func executeTemplate(tmpls *template.Template, tmplName string, w io.Writer, data interface{}) error {
var err error
layout := tmpls.Lookup("layout.html")
if layout == nil {
return errNoLayout
}
layout, err = layout.Clone()
if err != nil {
return err
}
t := tmpls.Lookup(tmplName)
if t == nil {
return errNoTemplate
}
_, err = layout.AddParseTree("content", t.Tree)
if err != nil {
return err
}
return layout.Execute(w, data)
}
Upvotes: 1
Reputation:
(2) If I want to have multiple pages with the same layout, the above will not work as it does not specify which content to load.
You need to build something for that matter.
It can be a template func, which knows the template, receives the block name and the args to call for t.executeTemplate, somehow like you did.
But this method has a severe drawback, as it requires that every request produces its own compiled template.
It can be a method of the view args. Which can let you build the template once, re use this instance for every request, only the argument will change.
No matter what, if you keep using the built in template
helper it can t be a variable, it is locked to use only static string.
Upvotes: 0