I'd like to compare two variables of string type inside a range loop as follows:
<select name="category" id="category">
{{range $c := .cats}}
<option value="{{$c.Title}}" {{ if eq $c.Title .category}}active{{end}}>{{$c.Title}}</option>
{{end}}
</select>
both $c.Title
and category
are strings dispatched by the controller.
However, instead on drop down menue being in the rendered template, I get :
can't evaluate field category in type model.category
$c
is of struct type category:
type Category struct {
ID int `db:"id"`
Title string `db:"title"`
Slug string `db:"slug"`
CreatedAt time.Time `db:"created_at"`
}
When I put directly the string value of category
instead of .category
in the code above, there is no issues.
I'm using gowebapp MVC framework, if it does matter.
How can I fix this?
Your .category
value you want to compare to is not part of your model
, but the template engine will attempt to resolve .category
as category
being a field or method of your model
value.
This is because the {{range}}
action sets the dot .
to the successive elements in each iteration.
To refer to the top-level category
, you may use the $
sign like this:
<select name="category" id="category">
{{range $c := .cats}}
<option value="{{$c.Title}}" {{ if eq $c.Title $.category}}active{{end}}>{{$c.Title}}</option>
{{end}}
</select>
See this runnable example:
func main() {
t := template.Must(template.New("").Parse(src))
params := map[string]interface{}{
"category": "Cars",
"cats": []struct{ Title string }{
{"Animals"}, {"Cars"}, {"Houses"},
},
}
if err := t.Execute(os.Stdout, params); err != nil {
panic(err)
}
}
const src = `<select name="category" id="category">
{{range $c := .cats}}
<option value="{{$c.Title}}" {{ if eq $c.Title $.category}}active{{end}}>{{$c.Title}}</option>
{{end}}
</select>`
Output (try it on the Go Playground):
<select name="category" id="category">
<option value="Animals" >Animals</option>
<option value="Cars" active>Cars</option>
<option value="Houses" >Houses</option>
</select>