-1

I'm playing with Go in a simple HTTP server:

// var tpl = template.Must(template.New("").Funcs(template.FuncMap{"isRegistered": isRegistered}).ParseGlob("templates/*")) // functions will be added later
var tpl = template.Must(template.ParseGlob("templates/*"))

func contact(w http.ResponseWriter, r *http.Request) {
    //// defined templates are: "home.html", "layout", "layout.html", "contact.html", "body"
    log.Println("in handler: ", tpl.DefinedTemplates())

    err := tpl.ExecuteTemplate(w, "contact.html", nil)
    if err != nil {
        fmt.Println(err) // no error displayed
    }
    // fmt.Fprintf((w), "write") - This works fine
}

func main() {

    log.Println("Serving on 8888 port")
    http.HandleFunc("/contact", contact)

    http.ListenAndServe(":8888", nil)
}


{{define "layout"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{.Title}}</title>
    <meta name="description" content="{{.Description}}">
    <link rel="canonical" href="{{.Canonical}}" />
</head>
<body>

{{template "body" .}}

</body>
</html>
{{end}}

{{define "body"}}
<h1>Contact us page</h1>

<p>
    Your name is...
</p>

{{end}}

The localhost:8888/contact returns OK 200 and empty body. I used this example: https://stackoverflow.com/a/36643663/2110953

But I need to add template functions in future also: var tpl = template.Must(template.New("").Funcs(template.FuncMap{"isRegistered": isRegistered}).ParseGlob("templates/*"))

DoctorP
  • 159
  • 2
  • 10

2 Answers2

3

Your contact.html does not "render" anything. It just defines the body template, but does not include it (execute it).

To execute a template (within a template), you may use the {{template}} action. To define and execute a template, you may use the {{block}} action.

Template Actions:

{{template "name"}}
    The template with the specified name is executed with nil data.

{{template "name" pipeline}}
    The template with the specified name is executed with dot set
    to the value of the pipeline.

{{block "name" pipeline}} T1 {{end}}
    A block is shorthand for defining a template
        {{define "name"}} T1 {{end}}
    and then executing it in place
        {{template "name" pipeline}}
    The typical use is to define a set of root templates that are
    then customized by redefining the block templates within.

If your goal is to have a "fixed" header and footer in all pages, then you have to restructure your templates. Have a header and footer template defined somewhere, and the pages should include them as first and last elements. See How to use a field of struct or variable value as template name?

icza
  • 389,944
  • 63
  • 907
  • 827
  • thank you but I don't understand what should if fix to make it work, just can't wrap my head around it, I understand that I should pass somehow layout.html AND handler's template (contact.html), but couldn't find a proper example – DoctorP Dec 05 '19 at 11:47
  • @DoctorP You don't see anything because your `contact.html` does not render anything, same as if it would be an empty file. Try to replace `{{define "body"}}` with `{{block "body" .}}` and see what happens. – icza Dec 05 '19 at 11:58
  • I want to include layout also into rendered output. https://stackoverflow.com/questions/36617949/how-to-use-base-template-file-for-golang-html-template block renders only current template – DoctorP Dec 05 '19 at 12:03
  • 1
    @DoctorP Then you have to restructure your templates. Have a `header` and `footer` template, and the page should include them as first and last elements. See [How to use a field of struct or variable value as template name?](https://stackoverflow.com/questions/28830543/how-to-use-a-field-of-struct-or-variable-value-as-template-name/28831138#28831138) – icza Dec 05 '19 at 12:12
0

Update: So I had to just create a header and footer templates:

{{template "header" .}}

<h1>Contact us page</h1>

<p>
    Your name is...
</p>


{{template "footer" .}}
{{define "header"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{.Title}}</title>
    <meta name="description" content="{{.Description}}">
    <link rel="canonical" href="{{.Canonical}}" />
</head>
<body>
{{end}}
{{define "footer"}}
</body>
</html>
{{end}}

and it worked fine

DoctorP
  • 159
  • 2
  • 10