Golang中如何修改主模板内的子模板

Golang中如何修改主模板内的子模板 我已在Go中成功使用模板,包括嵌套模板。但子模板是另一回事。我指的是在主模板中动态更改子模板。

我正在尝试创建一个多步骤表单页面。

<div class="content">
   <h2>Multi Step form</h2>
     <form action="/mail" method="post">
       {{template "form"}}  <----- 仅更改此子模板
     </form>
   </div>
</div>

这可行吗?或者有没有更聪明的方法来实现这个?

5 回复

要访问嵌套模板,请在模板名称后使用点号,如下所示:

{{template "form" . }}

更多关于Golang中如何修改主模板内的子模板的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


geosoft1:

因此,如果你想在它们之间切换,可以加载所有表单并按需显示/隐藏元素

谢谢。我已经尝试过文本操作,确信这个方法同样适用于子模板。

编辑代码 - JSFiddle - 代码游乐场

如果我的理解正确,您并不想修改嵌套模板中的内容,而是希望在多个模板之间进行切换。据我所知,模板并非动态内容,它们只是在加载时包含的静态文件。因此,如果您需要在模板间切换,可以选择加载所有表单并按需显示/隐藏元素(正如您已经做的那样),或者也可以直接在Go代码中执行您需要的特定模板。

geosoft1:

{{template “form” . }}

我有两个模板"form1"和"form2"(未使用或嵌套)。如何使用这种方法将模板从1更改为2?

<a href="/form2">Next page</a>

这个在"form1"中的按钮不起作用。

不过这种常见方式确实有效,但似乎有点笨拙(通过javascript或类似方式控制可见性):

<form action="/mail" method="post">
    <div id="1">{{template "form1"}}</div>
    <div id="2" style = "visibility: hidden;">{{template "form2"}}</div>
</form>

没有其他方法可以做到这一点吗?

是的,在Go语言中动态修改主模板内的子模板是完全可行的。你可以通过模板执行时传入不同的子模板定义来实现这一点。以下是几种实现方法:

方法1:使用模板组合

package main

import (
    "html/template"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    // 主模板
    mainTmpl := `
<div class="content">
   <h2>Multi Step form</h2>
     <form action="/mail" method="post">
       {{template "form" .}}
     </form>
   </div>
</div>`

    // 根据步骤选择不同的子模板
    step := r.URL.Query().Get("step")
    var subTmpl string
    
    switch step {
    case "1":
        subTmpl = `{{define "form"}}
        <div class="step1">
            <input type="text" name="name" placeholder="姓名">
            <input type="email" name="email" placeholder="邮箱">
            <button type="submit">下一步</button>
        </div>
        {{end}}`
    case "2":
        subTmpl = `{{define "form"}}
        <div class="step2">
            <input type="text" name="company" placeholder="公司">
            <input type="tel" name="phone" placeholder="电话">
            <button type="submit">提交</button>
        </div>
        {{end}}`
    default:
        subTmpl = `{{define "form"}}
        <div class="step1">
            <input type="text" name="name" placeholder="姓名">
            <input type="email" name="email" placeholder="邮箱">
            <button type="submit">下一步</button>
        </div>
        {{end}}`
    }

    // 解析并执行模板
    tmpl, err := template.New("main").Parse(mainTmpl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    tmpl, err = tmpl.Parse(subTmpl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    tmpl.Execute(w, nil)
}

方法2:使用模板文件

创建模板文件:

main.html

<div class="content">
   <h2>Multi Step form</h2>
     <form action="/mail" method="post">
       {{template "form" .}}
     </form>
   </div>
</div>

step1.html

{{define "form"}}
<div class="step1">
    <input type="text" name="name" placeholder="姓名">
    <input type="email" name="email" placeholder="邮箱">
    <button type="submit">下一步</button>
</div>
{{end}}

step2.html

{{define "form"}}
<div class="step2">
    <input type="text" name="company" placeholder="公司">
    <input type="tel" name="phone" placeholder="电话">
    <button type="submit">提交</button>
</div>
{{end}}

Go代码:

package main

import (
    "html/template"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    step := r.URL.Query().Get("step")
    var subTemplateFile string
    
    switch step {
    case "2":
        subTemplateFile = "step2.html"
    default:
        subTemplateFile = "step1.html"
    }

    // 解析模板
    tmpl, err := template.ParseFiles("main.html", subTemplateFile)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    tmpl.Execute(w, nil)
}

方法3:使用模板映射

package main

import (
    "html/template"
    "net/http"
)

var templates = map[string]string{
    "step1": `{{define "form"}}
        <div class="step1">
            <input type="text" name="name" placeholder="姓名">
            <input type="email" name="email" placeholder="邮箱">
            <button type="submit">下一步</button>
        </div>
        {{end}}`,
    "step2": `{{define "form"}}
        <div class="step2">
            <input type="text" name="company" placeholder="公司">
            <input type="tel" name="phone" placeholder="电话">
            <button type="submit">提交</button>
        </div>
        {{end}}`,
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    mainTmpl := `
<div class="content">
   <h2>Multi Step form</h2>
     <form action="/mail" method="post">
       {{template "form" .}}
     </form>
   </div>
</div>`

    step := r.URL.Query().Get("step")
    if step == "" {
        step = "step1"
    }

    subTmpl, exists := templates[step]
    if !exists {
        subTmpl = templates["step1"]
    }

    tmpl, err := template.New("main").Parse(mainTmpl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    tmpl, err = tmpl.Parse(subTmpl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    tmpl.Execute(w, nil)
}

这些方法都允许你在运行时动态更改主模板中的子模板内容,非常适合实现多步骤表单。第一种方法适合简单的场景,第二种方法适合模板较复杂的情况,第三种方法提供了更好的组织性。

回到顶部