I am creating a web project in Go and I have created it to some extent. But, I am stuck at one point. It would be great if I can get some help in that.
I have two files: sidebar.tmpl and index.tmpl and one main.go which is Parsing both templates and executing index.tmpl.
index.tmpl includes sidebar.tmpl using {{ template "Sidebar" }}.
I am using the following struct to send data.
type Groups struct {
Id int
Name string
Parent string
ParentsList map[int]string
}
One index.tmpl, I am showing data from DB in table format.
But, in sidebar.tmpl I am trying to show the same data as in index.tmpl using the range: {{ range . }}
Hey @andersk, it would be easier to help you if you could possibly show some of the code you are having trouble with
Either way, one thing you should make sure you are doing is checking all errors from your template output, for example:
t := template.New("t").ParseFiles("index.tmpl", "sidebar.tml")
if err := t.ExecuteTemplate(os.Stdout, "index.tmpl", data); err != nil {
// Check error here.
}
Are you actually trying to range over a slice or map of Groups? If not, range isn’t what you want. For example, if you want to range over ParentsList, then you would use range .ParentsList.
Edit: Here’s an example of what I mean, where a slice of data will work, but an individual item won’t, when trying to use range:
package main
import (
"html/template"
"log"
"os"
)
type Data struct {
Name string
}
var indexSrc = `
{{range .}}
{{.Name}}
{{end}}
`
var t = template.Must(template.New("t").Parse(indexSrc))
func main() {
data := []Data{
{Name: "Benjamin"},
{Name: "Radovsky"},
} // <-- Works
// data := Data{
// Name: "Benjamin",
// } <-- Doesn't work.
if err := t.Execute(os.Stdout, data); err != nil {
log.Fatalln(err)
}
}
type Groups struct {
Id int
Name string
Parent string
ParentsList map[int]string
}
var tmpl = template.Must(template.ParseFiles("src/alp/admin/temps/group/index.tmpl", "src/alp/admin/temps/includes/footer.tmpl", "src/alp/admin/temps/includes/header.tmpl", "src/alp/admin/temps/includes/sidebar.tmpl"))
// Function Index shows all values on home
func Grp_Index(w http.ResponseWriter, r *http.Request) {
// Open database connection
db, err := funcs.DbOpenConn()
selDB, err := funcs.DbQueryGetRows(db, "SELECT * FROM groups ORDER BY id DESC")
funcs.CheckErr(err)
// Call the struct to be rendered on template
n := Groups{}
// Create a slice to store all data from struct
res := []Groups{}
// Read all rows from database
for selDB.Next() {
// Must create this variables to store temporary query
var id int
var name, parent string
// Scan each row storing values from the variables above and check for errors
err = selDB.Scan(&id, &name, &parent)
if err != nil {
panic(err.Error())
}
// Get the Scan into the Struct
n.Id = id
n.Name = name
n.Parent = parent
// Join each row on struct inside the Slice
res = append(res, n)
}
// Execute template `Index` from `tmpl/*` folder and send the struct
// (View the file: `tmpl/Index`
tmpl.ExecuteTemplate(w, "Group_Index", res)
// Close database connection
defer db.Close()
}
And see what output you get since I’m guessing there’s an error somewhere there.
On second thought I’m pretty sure you need to change this part (w, "Group_Index", res) to this (w, "index.tmpl", res) since you don’t actually have a template called Group_Index and when you change it to index.tmpl, it should fix your issue, but once again make sure you check your errors anyway.
Oh wait a second, is it working fine with index.tmpl but just not working with sidebar.tmpl?
If that’s the problem, you need to use this: {{ template "Sidebar" . }} instead of {{ template "Sidebar" }}, to pass the data from the index template into the sidebar template.
If there is a mismatch between your template and the data you feed it, such as trying to range over something that is not rangeable, the error from Execute will tell you this. That you are seeing no errors when you are not checking for errors does not mean there aren’t any. You should heed @radovskyb’s advice here.
I have a feeling he’s just forgotten to pass the data through to the second template, so if that’s the case, I’m pretty sure even if he added error checking like I suggested above, there most likely wouldn’t be an error returned for it, but yeah either way, got to always check them errors
Hmm, I can’t exactly remember where I saw it in the actual docs (I constantly read the source for Go packages that I use when I am writing code and get curious, so might have seen it there one time), possibly in the text/template package rather than the html/template package. There’s one example you can see around here in text/template, in the block example: https://golang.org/pkg/text/template/#hdr-Actions.
However if you want to read up on it, I would probably try to google something along the lines of golang nested template pipeline.