In html/template, is it possible to "extend" a block?

Hello everyone, I think it’s better to explain my question via code:

{{define "base"}}
    <h1>An example template</h1>
    {{block "sidebar" .}}
        <p>My default sidebar content</p>
    {{end}}
{{end}}

<!-- child1.html -->
{{template "base" .}}

<!-- 
    I want this page's sidebar to show:
    <p>My default sidebar content</p>
-->
<!-- 
    Answer: just do nothing
-->

<!-- child2.html -->

{{template "base" .}}
<!-- 
    I want this page to show:
    <p>My default sidebar content</p>
    <p>My custom sidebar content</p>
-->

{{define "sidebar"}}
    <!-- Answer: ??? -->
{{end}}

<!-- child3.html -->

{{template "base" .}}
<!-- 
    I want this page's sidebar to show:
    <p>My custom sidebar content</p>
    <p>My default sidebar content</p>
-->

{{define "sidebar"}}
    <!-- Answer: ??? -->
{{end}}

I’ve used this particular feature from Django[1] and Laravel[2], and am wondering how to implement it with Go templates.

Thank you!

[1] How to override templates | Django documentation | Django
[2] Blade Templates - Laravel - The PHP Framework For Web Artisans

This might be of use:

I was reading this thread earlier as well – it did help me understand how to correctly order my template parsing so overriding works properly. Unfortunately I don’t think it covers my particular question.

As I understand it you want a base template and use templates for each page inside the base template. I tried to achieve this, but I gave up. Now I am using “components” at page level. Not bad approach, but not the way I wanted from the beginning. I have found this good enough and easy to reuse components instead.

I’m not sure I fully understand what you’re after, but what about something like this?

package main

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

var baseTemplate = `{{define "base"}}
    <h1>An example template</h1>
        <p>My default sidebar content</p>
        {{block "sidebar" .}}
        {{end}}
{{end}}`

var childTemplate = `{{template "base" .}}`

var childTemplateWithCustom = `{{template "base" .}}
{{define "sidebar"}}<p>Custom sidebar template</p>{{end}}`

func main() {
	baseTmpl := template.Must(template.New("baseTemplate").Parse(baseTemplate))

	childTmpl, _ := template.Must(baseTmpl.Clone()).Parse(childTemplate)
	fmt.Println("No custom content:")
	childTmpl.Execute(os.Stdout, nil)

	childTmplWithCustom, _ := template.Must(baseTmpl.Clone()).Parse(childTemplateWithCustom)
	fmt.Println("Custom content:")
	childTmplWithCustom.Execute(os.Stdout, nil)
}

… which outputs:

No custom content:

    <h1>An example template</h1>
        <p>My default sidebar content</p>
        
        
Custom content:

    <h1>An example template</h1>
        <p>My default sidebar content</p>
        <p>Custom sidebar template</p>

You can run it on the go playground if you want. Also check out the docs for sharing template building blocks with other templates:

They call them “driver templates” but the idea is basically re-usable base templates that you .Clone for use in other templates.

Thanks for this, but this doesn’t allow me to replace the default sidebar at all because it’s outside of the block. I think I got enough feedback from other sources as well that there’s no exact way to do this with html/template. I just resorted to this implementation that is close enough to what I want:

I appreciate the help, really!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.