1
votes

I am using gin gonic and it's features. One if them being html template rendering. So in spirit of DRY I wanted to create a base.html template with all common html tags etc. with a slot for different page bodies.

In essence, this is the base.html

{{define "base"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

{{ template "main" . }}

</body>
</html>
{{end}}

Then I created a "child" template called home.html:

{{template "base" .}}

{{define "main"}}
    <div class="container mt-5">
        Hello
    </div>
{{end}}

I followed this wonderful guide on this page and it worked like a charm.

The problem

But when I tried adding another page with different body in subpage.html eg:

{{template "base" .}}

{{define "main"}}
<div class="container">
    <div>
        <h2>This page is still in progress</h2>
    </div>
</div>
{{end}}

the last template that is picked by gins LoadHTMLFiles or LoadHTMLGlob, is then displayed on every page. In this case this is subpage.html content. How do I fix this. Is it even possible to achieve this behaviour by default?

1
The first thing that comes to mind that you could do is to split base into two top/bottom or header/footer, then each of your mains would call top at the top and bottom at the bottom, also each of your mains ought to have a unique name if you want to avoid the original problem, actually you can drop the "main" name altogether and just make sure that each handler renders their corresponding template by using the template file's unique base name.mkopriva
Hmm, thats one way to go. But imagine having many subpages like this. I find it quite inefficient. I am coming from django environment and it already has these features of template inheritance.Razmooo
What is inefficient? This actually reduces your version of the code by one line per template. Maybe you misunderstood what I'm suggesting, or I misunderstood what you're asking. I'll provide an answer with an example to make it more clear what I mean, you can then comment on why it's not good solution for you.mkopriva
Note that you could make your initial template design work, Go supports that. Basically instead of using something like LoadHTMLFiles/LoadHTMLGlob that parses all the files together and relies on the uniqueness of their names to know which one you want to render, you would parse each page-specific template file together with its dependencies but separate from other page-specific template files, this way you end up with one *template.Template object per each page handler and you then execute that template object from its corresponding handler.mkopriva

1 Answers

1
votes

You could do something like this:

base.html

{{ define "top" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{{ end }}

{{ define "bottom" }}
</body>
</html>
{{ end }}

home.html

{{ template "top" . }}

<div class="container mt-5">
    Hello
</div>

{{ template "bottom" . }}

subpage.html

{{ template "top" . }}

<div class="container">
    <div>
        <h2>This page is still in progress</h2>
    </div>
</div>

{{ template "bottom" . }}

Then make sure you're using the file's base name:

// in the home handler use the following
c.HTML(http.StatusOK, "home.html", data)

// in the subpage handler use the following
c.HTML(http.StatusOK, "subpage.html", data)