Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have nested templates in Go using the standard library?

How do I get nested templates like Jinja has in the python runtime. TBC what I mean is how do I have a bunch of templates inherit from a base templates, just filing in blocks of the base templates, like Jinja/django-templates does. Is it possible using just html/template in the standard library.

If that is not a possibility, what are my alternatives. Mustache seems to be an option but would I then be missing out on those nice subtle features of html/template like the context sensitive escaping etc.? What other alternatives are ther?

(Environment: Google App Engin, Go runtime v1, Dev - Mac OSx lion)

Thanks for reading.

like image 768
Sri Kadimisetty Avatar asked Jul 13 '12 09:07

Sri Kadimisetty


People also ask

Can templates be nested?

As mentioned in Gotchas of using template in HTML5Rocks tutorial: Activating the outer template will not active inner templates. That is to say, nested templates require that their children also be manually activated.


2 Answers

Yes it is possible. A html.Template is actually a set of template files. If you execute a defined block in this set, it has access to all the other blocks defined in this set.

If you create a map of such template sets on your own, you have basically the same flexibility that Jinja / Django offers. The only difference is that the html/template package has no direct access to the file system, so you have to parse and compose the templates on your own.

Consider the following example with two different pages ("index.html" and "other.html") that both inherit from "base.html":

// Content of base.html: {{define "base"}}<html>   <head>{{template "head" .}}</head>   <body>{{template "body" .}}</body> </html>{{end}}  // Content of index.html: {{define "head"}}<title>index</title>{{end}} {{define "body"}}index{{end}}  // Content of other.html: {{define "head"}}<title>other</title>{{end}} {{define "body"}}other{{end}} 

And the following map of template sets:

tmpl := make(map[string]*template.Template) tmpl["index.html"] = template.Must(template.ParseFiles("index.html", "base.html")) tmpl["other.html"] = template.Must(template.ParseFiles("other.html", "base.html")) 

You can now render your "index.html" page by calling

tmpl["index.html"].Execute("base", data) 

and you can render your "other.html" page by calling

tmpl["other.html"].Execute("base", data) 

With some tricks (e.g. a consistent naming convention of your template files), it's even possible to generate the tmpl map automatically.

like image 184
tux21b Avatar answered Nov 16 '22 00:11

tux21b


note, when you execute your base template, you must pass values down to the child templates, here I simply pass ".", so that everything is passed down.

template one displays {{.}}

{{define "base"}} <html>         <div class="container">             {{.}}             {{template "content" .}}         </div>     </body> </html> {{end}} 

template two displays {{.domains}} that's passed into the parent.

{{define "content"}} {{.domains}} {{end}} 

Note, if we used {{template "content" .}} instead of {{template "content" .}}, .domains wouldn't be accessible from the content template.

DomainsData := make(map[string]interface{})     DomainsData["domains"] = domains.Domains     if err := groupsTemplate.ExecuteTemplate(w, "base", DomainsData); err != nil {         http.Error(w, err.Error(), http.StatusInternalServerError)     } 
like image 40
robert king Avatar answered Nov 16 '22 00:11

robert king