How to use partials in html/template

What’s the preferred approach to passing data to a template and partials inside a page?

I have a block “thread” with replies, whos appearance depends on the page it is rendered on:

{{define "thread"}}
    {{$isThreadPage := .IsThreadPage}}
    {{$thread := .Thread}}

    {{if $threadPage}}
        {{$thread.Subject}}
    {{else}}
        <a href="/threads/{{$thread.ID}}">{{$thread.Subject}}</a>
    {{end}}
    {{range $thread.Replies}}
        {{template "reply" .}}
    {{end}}
{{end}}

I use it in my thread page like this, where dict is a function I defined to create a map with key/value pairs:

{{define "title"}}
    {{with .Thread}}
        {{.Subject}}
    {{end}}
{{end}}
    
{{define "content"}}
    {{with .Thread}}
        {{template "thread" (dict "Thread" . "ThreadPage" true)}} 
    {{end}}
{{end}}

I think for a simple website this approach would work, but I want to learn and hear if there is anything I can do to improve my workflow with html/template.

Two things first.

You have a bug: you assign $isThreadPage but test $threadPage — that variable doesn’t exist, so the condition is always false and the link always renders.

Second, dict returns map[string]any. A typo in a key name produces no error at all, just silent wrong behavior.

For the architecture question: the root problem is that html/template gives you a single . and you lose parent context on every range. Passing context down manually works but scales poorly as nesting deepens.

The cleaner approach is a recursive node struct that carries its own render context — each node holds its data, its children, and whatever flags it needs. The template just recurses and never needs to ask “where am I being rendered?”.

I built something along these lines for a forum system here: https://github.com/hazyhaar/horum — might be worth a look if you’re going deeper with recursive thread/reply structures.

One question though: are you learning html/template specifically, or are you building something you intend to ship?

If it’s the latter, templ is worth considering. Components are typed Go functions with explicit parameters — your ThreadView struct becomes a function signature, the compiler checks everything, and context propagation through nested components is trivial. The entire class of problem you’re hitting doesn’t exist in templ.

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