Fabian
Fabian

Reputation: 561

Only proceed if []struct is not empty

I have an []struct that can have no content but also it is possible that it has content:

Anleitung  []struct {
    Name string `json:"blog"`
    Link string `json:"link"`
} `json:"anleitung"`

In my template I try to check if Anleitung contains something, and only then proceed:

{{ ne $jb.Anleitung "" }}
     <div class="btn-group">
        <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              <span class="badge">4</span> Anleitungen <span class="caret"></span>
        </button>
        <ul class="dropdown-menu">
            {{ range $anl := $jb.Anleitung }}
                 <li><a href="{{ $anl.Link }}?ref=jbguide">{{ $anl.Name }}</a></li>
             {{ end }}
         </ul>
      </div>
{{ end }}

compiling the whole thing gives me the following error:

Error rendering index template: template: index.tmpl:131: unexpected {{end}}

Row no 131 is the last row in the template file.

Is there a way to check if the []struct contains any data?

Upvotes: 1

Views: 862

Answers (2)

icza
icza

Reputation: 418127

You may simply use the {{with}} action. Quoting from the package doc of text/template:

{{with pipeline}} T1 {{end}}
    If the value of the pipeline is empty, no output is generated;
    otherwise, dot is set to the value of the pipeline and T1 is
    executed.

Since {{with}} also sets the pipeline, modify your {{range}} to this:

{{ range $anl := . }}

Using it:

{{ with $jb.Anleitung }}
     <div class="btn-group">
        <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              <span class="badge">4</span> Anleitungen <span class="caret"></span>
        </button>
        <ul class="dropdown-menu">
            {{ range $anl := . }}
                 <li><a href="{{ $anl.Link }}?ref=jbguide">{{ $anl.Name }}</a></li>
             {{ end }}
         </ul>
      </div>
{{ end }}

Going further, you can simplify the {{range}} as we don't need the $anl variable, {{range}} also sets the pipeline:

{{ range . }}
    <li><a href="{{.Link}}?ref=jbguide">{{.Name}}</a></li>
{{ end }}

Testing it:

t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{}
fmt.Println("First, no params:")
if err := t.Execute(os.Stdout, m); err != nil {
    fmt.Println(err)
}

fmt.Println("Next, 2 values:")
m = map[string]interface{}{
    "Anleitung": []struct {
        Name string `json:"blog"`
        Link string `json:"link"`
    }{
        {"Bob", "http://google.com"},
        {"Alice", "http://amazon.com"},
    },
}
if err := t.Execute(os.Stdout, m); err != nil {
    fmt.Println(err)
}

Output (try it on the Go Playground):

First, no params:

Next, 2 values:


     <div class="btn-group">
        <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              <span class="badge">4</span> Anleitungen <span class="caret"></span>
        </button>
        <ul class="dropdown-menu">

                 <li><a href="http://google.com?ref=jbguide">Bob</a></li>

                 <li><a href="http://amazon.com?ref=jbguide">Alice</a></li>

         </ul>
      </div>

Upvotes: 3

Jonathan Hall
Jonathan Hall

Reputation: 79674

Two things:

  1. Your ne syntax is wrong. It needs to begin with if, then your {{ end }} will no longer be a syntax error.
  2. Your struct is never going to equal "", because it's not a string. If you want to know if the slice is empty, you must check its length. The way to do this in a template is, as documented, with pipeline. This will, in effect, render #1 obsolete.

Upvotes: 1

Related Questions