9

The use of if statements inside templates really is puzzling me.

I'm trying to put a class = "active" inside a nav list made with golang templates, to do a basic tab menu that detects the active tab. Here's my attempt :

{{define "header"}}
<!DOCTYPE html>
<html>
    <head>
        <title>Geoprod</title>
        {{template "stylesheet" .}}
    </head>
    <body>
        <nav class="navbar" role="navigation">
          <div class="navbar-header">
            <a{{if eq .Active "accueil"}} class="active"{{end}} href="/">Geoprod</a>
          </div>
          <div class="navbar-body">
            <ul class="navbar-list">
                <li{{if eq .Active "societe"}} class="active"{{end}}><a href="/societe">Soci&eacutet&eacute</a></li>
                <li{{if eq .Active "dossier"}} class="active"{{end}}><a href="/dossier">Dossier</a></li>
                <li{{if eq .Active "temps"}} class="active"{{end}}><a href="/temps">Temps</a></li>
                <li{{if eq .Active "mails"}} class="active"{{end}}><a href="/mails">Mails</a></li>
            </ul>
          </div>
        </nav>
{{end}}

And in main.go :

var FuncMap = template.FuncMap{
    "eq": func(a, b interface{}) bool {
        return a == b
    },
}
var templates = template.Must(template.ParseGlob("templates/*.html"))

and in func main()

templates.Funcs(FuncMap)

The program compiles, but i've found out adding the {{if eq .Active "something"}} class="active"{{end}} (^^ which I included here) causes the program to not display any text anymore. Any idea why?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Nicolas Marshall
  • 4,186
  • 9
  • 36
  • 54
  • 3
    2 things. Did you check for errors on execute? Also: you have to call the Funcs() before parsing the templates. Otherwise the funcs will not be known. On the other hand: the eq func is already defined http://golang.org/pkg/text/template/#hdr-Functions – seong Jul 15 '14 at 10:18
  • 1: Nope, no errors in the log 2: Strange, i just read [this](https://groups.google.com/d/msg/golang-nuts/vQfqhTszj4c/MSNfUnsDod0J) this morning, Rob Pike saying it's up to each one of us to write this function if we need it. Is this a new addition to Go ? – Nicolas Marshall Jul 15 '14 at 10:30
  • 1
    if there is no output at all, there has to be an error. Also your implementation of `eq` is lacking. Please have a look here: http://golang.org/ref/spec#Comparison_operators Especially the part with comparing interface values. – seong Jul 15 '14 at 10:53
  • Are you sure it is the {{if}} expression cause the problem? It looks like you got wrong template name, try change {{define "header"}} to {{define "header.html"}} – chendesheng Jul 15 '14 at 12:21
  • Removing the if causes the page to display as intended (only the code doesn't contain the `class="active"`). The header template is in the file header.html, should I also change the name of the template ? – Nicolas Marshall Jul 15 '14 at 13:04
  • @seong How do you call Funcs() before parsing ? All the examples I found were with `templates.New("").Funcs(...)`, but here my templates are already named from within templates, So i can't use templates.New(), can I ? What would be a correct syntax then ? – Nicolas Marshall Jul 15 '14 at 13:08
  • @seong Let's say i stick to the built-in eq function for now. Is the syntax of my {{if}} statement correct ? Also, where can i find documentation on that `.Active` ? I copied it from [here](http://stackoverflow.com/questions/18352192/css-class-based-on-loaded-template), but i really can't find anything about it in the official template doc. – Nicolas Marshall Jul 15 '14 at 13:11
  • 1
    The dot `.` is your pipeline (on the top level whatever you passed to the `Execute*()` methods as the data). If `.Active` is not set, this might already be your problem. But this indicates you are not checking your `Execute` error. Please show the code where you `Execute()`. – seong Jul 15 '14 at 13:19
  • 2
    check this: http://play.golang.org/p/wr59HYR8gt – chendesheng Jul 15 '14 at 13:21
  • @seong Indeed, my function where templates are executed doesn't check for errors, because I "just wanted to test something quickly". Mistake I'll remember. I'll fix this and come back with an error log. – Nicolas Marshall Jul 15 '14 at 13:27
  • @seong So, this is my error log, and it makes my mistake quite clear : `executing "header" at <.Active>: Active is not a field of struct type *main.Page` . I just thought `.Active` was some sort of built-in, of course it's not in the doc. I'll replace .Active with a field i actually have, and come back to tell you if that works. – Nicolas Marshall Jul 15 '14 at 13:38
  • @chendesheng It's a lot like what you sent me on playground, in the end. Thanks to you too. – Nicolas Marshall Jul 15 '14 at 13:55
  • One more thing : should I write an answer summing up my mistakes just to tag the question as solved ? – Nicolas Marshall Jul 16 '14 at 08:07
  • 1
    @NicolasM Please do. This is hard to follow otherwise. – user918176 May 02 '15 at 17:15
  • Just to check: does my answer do what you want? – jochen Nov 12 '16 at 23:01
  • I guess no need to add `FuncMap`. There is in-build function `eq` in `html/template`. And what is the value of `.Active`? Itmust be a string. – Bhavana Dec 01 '16 at 12:59

1 Answers1

5

I tried to convert your code into a minimal working example, and I believe your code and template works as expected. You can see my code (and run it) on the Go Playground.

My guess about what went wrong: Did you notice that {{define ...}} only defines a template for future use. You will still need to tell Go to actually use this template, either by using {{ template "header" }} or similar in a main template, or by using templates.ExecuteTemplate.

jochen
  • 3,728
  • 2
  • 39
  • 49