How to test if a Go template block is defined?

Viewed 65

I'm using Go 1.19 with the built-in HTML template engine. Is there a way to test if a block is defined in a particular template file?

Specifically, I want to implement optional header entries in the Go HTML template.

I have a general layout template that includes a content template when rendered.

I want to implement as below...

Currently, the <meta name="description" content="{{block "description" .}}{{end}}"> result in an empty description tag. I'd like to not have the tag at all if there is nothing in it.

Any ideas?

layout.gohtml (simplified)[updated]

<html>
<head>
    <title>{{block "title" .}}The Title{{end}}</title>
    {{if .renderDescription}}
        <meta name="description" content="{{template "description"}}">
    {{end}
</head>
<body>
    <header></header>
    {{template "content" .}}
    <footer></footer>
</body>
</html>

content1.gohtml

{{define "title"}}The 2hO Network{{end}}
{{define "description"}}An options description{{end}}
{{define "content"}}
    Vestibulum ante ipsum primis in faucibus...
{{end}}

content2.gohtml

{{define "title"}}The 2hO Network{{end}}
{{define "content"}}
    Vestibulum ante ipsum primis in faucibus...
{{end}}
1 Answers

Templates are designed to be statically analyzable. This means if you don't have a description template, you'll get an error when parsing the templates.

Instead use an {{if}} action to check if the description template needs to be rendered. The description template maybe empty.

For example:

{{if .renderDescription}}
    {{template "description"}}
{{end}}

{{define "description"}}description content{{end}}

If you have to check the .renderDescription in many places, you may also move the check (the {{if}} action) into the template, so you can unconditionally use {{template}} (but you still have to provide a pipeline that contains the condition):

{{template "description" .}}


{{define "description"}}
    {{if .renderDescription}}
        description content
    {{end}}
{{end}}

Notes:

The {{block}} action is not to include a template, it is to define and include a template. To include a template defined elsewhere, use {{template}}.

You also have to change your template structuring. Instead of having a "frame" template embedding a "content", define "header" and "footer" templates, and have each page have its own template, which include "header", the content and "footer".

Related