gogo-templatesgo-html-template

Why don't HTML templates that I have parsed work?


I parsed my template files to make it easier for me to work.

I named them {{define "pagearea"}}. For example {{define "footer"}}.

Folder layout

main.go

package main

import (
    "log"
    "os"
    "html/template"
)

type Home struct {
    Sitelang string
    Sitetitle string
    Sitename         string
    Siteslogan string
}

func main() {
    homeTmpl, err := template.ParseFiles("./topheader.tmpl", "./footer.tmpl",  "./index.tmpl")
    if err != nil {
        log.Fatal("Home page parsing error:", err)
    }

    data := Home{Sitelang: "en",
        Sitetitle: "Home - Render Test",
        Sitename        : "test 1",
        Siteslogan: "mmmmeeeeeuaawww!"}
        homeTmpl.Execute(os.Stdout, data)

}

footer.tmpl:

{{define "footer"}}
<footer>

    <small>
        This is footer area. Test.</small>
</footer>
</body>
</html>
{{end}}

index.tmpl:

{{template "topheader"}}

<h1>
        Main area</h1>

{{template "footer"}}

topheader.tmpl:

{{define "topheader"}}
<!DOCTYPE html>
<html lang="
        {{.Sitelang}}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>
        {{.Sitetitle}}</title>

</head>

<body>
<header>
    <h1>
            {{.Sitename}}
    </h1>
    <p>
            {{.Siteslogan}}
    </p>
</header>


{{end}}

Build command: go build .

I really don't know what I'm missing. What's wrong here?


Solution

  • You used template.ParseFiles() to parse the template files. This will parse all files, and return a template that will "contain" all parsed templates as associated templates. The returned template.Template will represent the first template. Quoting from template.ParseFiles():

    The returned template's name will have the (base) name and (parsed) contents of the first file.

    Then you use Template.Execute() which executes the template whose method you're calling. So in your case that will be topheader.tmpl, but that template does not generate any output, that template just defines a template: {{define "topheader"}}.

    Most likely you want to execute the index.tmpl, so use Template.ExecuteTemplate() where you can identify the executable template by its name (and don't forget to check the returned error):

    err = homeTmpl.ExecuteTemplate(os.Stdout, "index.tmpl", data)
    if err != nil {
        log.Fatal("index template execution failed:", err)
    }
    

    Another mistake is that when your index.html template includes (executes) other templates using the {{template}} action, you don't pass any parameter to them, yet you want to use the initial parameters.

    So pass the current params when invoking other templates. Your index.html should be:

    {{template "topheader" .}}
    
    <h1>
            Main area</h1>
    
    {{template "footer" .}}
    

    See related questions:

    Go template name

    Golang template engine pipelines