我正在尝试动态更改内容。但是内容保持不变。似乎要获取第一个比赛。无论模板是什么。即使使用硬编码的文件名也不起作用。该代码可以正常工作,但是内容无法更改。
主要布局
{{define "layout"}}
<html>
<body>
{{ template "content" }}
</body>
</html>
{{end}}
子模板1
{{ define "content" }}
<h1 style="color: red;">Page 1!</h1>
{{ end }}
子模板2
{{ define "content" }}
<h1 style="color: blue;">Page 2!</h1>
{{ end }}
执行代码
package main
import (
"html/template"
"net/http"
"strings"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
switch path {
case "":
path = ("index.gohtml")
default:
path = (path + ".gohtml")
}
err := tpl.ExecuteTemplate(w, "layout", path)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
我也尝试过在运气不佳之前执行ParseFiles。我在做什么错了?
答案 0 :(得分:2)
我认为,在解析模板之后调整路径为时已晚。
什么可行(尽管我不确定这里是否是最优雅的解决方案)是使用AddParseTree
方法:
AddParseTree为具有给定名称的模板添加解析树,并且 将其与t相关联。如果模板尚不存在,它将 创建一个新的。如果该模板确实存在,它将被替换。
根据您的情况,根据条件,您将先Parse
相关的模板文件(子模板1或2),然后将AddParseTree
添加到tpl
,然后再进行操作执行它。
答案 1 :(得分:0)
最后我使它起作用,但是只有在不遵循手册的情况下。
解决方案第1部分
在模板中跳过{{define}}和{{end}}。奇怪...
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
layout level
{{ template "content" . }}
</body>
</html>
在子模板中也是如此...
<h1 style="color: red;">Page 1!</h1>
解决方案第2部分
我找到了Eli提到的带有AddParsTree的代码片段,这是代码(简化后没有错误处理)
package main
import (
"html/template"
"net/http"
"strings"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.html"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
switch path {
case "":
path = ("home.html")
default:
path = (path + ".html")
}
layout := tpl.Lookup("layout.html")
layout, _ = layout.Clone()
t := tpl.Lookup(path)
_, _ = layout.AddParseTree("content", t.Tree)
layout.Execute(w, "")
我真的不明白为什么我必须不遵守手册才能使它起作用。任何启发我的评论将不胜感激。
答案 2 :(得分:0)
我遇到了同样的问题,并以这种方式解决了:
这适用于 {{ define "content1" }}...{{ end }}
语法,但您必须为模板指定唯一名称:content1
和 content2
。
我制作了一个用于处理模板内容的包。
package templates
import (
"html/template"
"log"
"net/http"
)
var tmpls *template.Template
// LoadTemplates parses a template folder
func LoadTemplates(tmplPath string) {
tmpls = template.Must(template.ParseGlob(tmplPath))
}
// ExecTmpl executes a template and writes it
func ExecTmpl(w http.ResponseWriter, tmpl string, data interface{}) {
tmpls.ExecuteTemplate(w, tmpl, data)
}
// ExecTmplTree combines and executes two templates
func ExecTmplTree(w http.ResponseWriter, outer, inner string, data interface{}) {
layout, err := tmpls.Lookup(outer).Clone()
if err != nil || layout == nil {
log.Fatal("ExecTmplTree: Could not get a copy of template", outer)
}
content, err := tmpls.Lookup(inner).Clone()
if err != nil || content == nil {
log.Fatal("ExecTmplTree: Could not get a copy of template", inner)
}
_, err = layout.AddParseTree("content", content.Tree)
if err != nil {
log.Fatal("ExecTmplTree: Templates could not be combined.")
}
layout.Execute(w, data)
}
然后我按如下方式调用函数(在 main.go 或其他地方):
// call first to load templates from the folder where your templates are stored
// you might need fit the file ending, too, I simply use .html for html-templates
func init() {
templates.LoadTemplates("web/templates/*.html")
}
// write a basic template without nesting
func exampleHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecTmplTree(w, "content1", "messageForm", nil)
}
// write nested templates. here, index is the outer template
// and code is the inner
func indexHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecTmplTree(w, "layout", "content1", nil)
}