1

I have been trying to use nested templates in Go, however the Examples or help documents are not helping me, and examples in 3 other blogs are not what I'm looking for (one is close and maybe the only way but I want to make sure)

OK, so my code is for App Engine, in here I will be doing an urlfetch to a server, and then I want to show some results, like the Response, headers, and body.

const statusTemplate = `
{{define "RT"}}
Status      - {{.Status}}
Proto       - {{.Proto}}
{{end}}
{{define "HT"}}
{{range $key, $val := .}}
{{$key}} - {{$val}}
{{end}}
{{end}}
{{define "BT"}}
{{.}}
{{end}}
{{define "MT"}}
<html>
    <body>
        <pre>
-- Response --
{{template "RT"}}

--  Header  --
{{template "HT"}}

--   Body   --
{{template "BT"}}
        </pre>
    </body>
</html>
{{end}}
{{template "MT"}}`

func showStatus(w http.ResponseWriterm r *http.Request) {
    /*
     *  code to get:
     *  resp as http.Response
     *  header as a map with the header values
     *  body as an string wit the contents
     */
    t := template.Must(template.New("status").Parse(statusTemplate)
    t.ExecuteTemplate(w, "RT", resp)
    t.ExecuteTemplate(w, "HT", header)
    t.ExecuteTemplate(w, "BT", body)
    t.Execute(w, nil)
}

My code actually outputs the RT, HT, and BT templates with the correct values, and then it outputs the MT template empty (MT stands for main template).

So... How can I use nested forms from a string variable so that an example as the above works?

2 Answers 2

1

I think the approach you try with nested templates is wrong. If you want . to be defined inside a nested template, you have to supply an argument to the call to the nested template, just as you do with the ExecuteTemplate function:

{{define "RT"}}
Status      - {{.Status}}
Proto       - {{.Proto}}
{{end}}
{{define "HT"}}
{{range $key, $val := .}}
{{$key}} - {{$val}}
{{end}}
{{end}}
{{define "BT"}}
{{.}}
{{end}}
{{define "MT"}}
<html>
    <body>
        <pre>
-- Response --
{{template "RT" .Resp}}

--  Header  --
{{template "HT" .Header}}

--   Body   --
{{template "BT" .Body}}
        </pre>
    </body>
</html>
{{end}}
{{template "MT"}}

The important part you seem to miss is that templates do not encapsulate state. When you execute a template, the engine evaluates the template for the given argument and then writes out the generated text. It does not save the argument or anything that was generated for future invocations.

Documentation

Relevant part of the documentation:

Actions

Here is the list of actions. "Arguments" and "pipelines" are evaluations of data, defined in detail below.

...

{{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.

...

I hope this clears up things.

Sign up to request clarification or add additional context in comments.

3 Comments

So what I should be doing is change my template as you suggested, and make a map|structure to send in those values? if that's the case, would I need to {{template "MT" .}}?
@Goodwine Not quite; in the example code you gave, you create a template "status" that calls "MT" with nil data. You defined MT as a subtemplate; just use ExecuteTemplate(w,"MT",data) instead (or use {{template "MT" .}}).
I am using {{template "MT" .}} tho
0

have a look at this tutorial:
http://javatogo.blogspot.com

there it is explained how to use nested templates.

1 Comment

Oh~ I haven't stumbled upon this blog post, it is not exactly what I wanted tho, because it's separating the templates, and the Go documents say that I should be able to do what I am trying to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.