Go Templating Issue

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 . }}

but it is not showing anything.

So, what is the best way to do it?

Thanks

Hey @andersk, it would be easier to help you if you could possibly show some of the code you are having trouble with :slight_smile:

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)
	}
}

Thanks for your reply.

Here is the code that I am using:

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()
}

Hey @andersk, I was mainly referring to the template’s code, but that is good to see :slight_smile:

Can you change this:

tmpl.ExecuteTemplate(w, "Group_Index", res)`

To this:

if err := tmpl.ExecuteTemplate(w, "Group_Index", res); err != nil {
    log.Fatalln(err)
}

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.

The code is working fine. There are no errors. But, if you see there is one more template:
src/alp/admin/temps/includes/sidebar.tmpl

I have named the following template as : Group_Index
src/alp/admin/temps/group/index.tmpl

I want to run the range code in that too:
> {{ range . }}
>


> {{ .Name }}
> {{ .Parent }}
>
> {{ end }}

It is not working in the included template.

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.

Once you change {{ template "Sidebar" }} to {{ template "Sidebar" . }}, if it still does’t work, let me know, but I’m pretty certain it will.

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. :slight_smile:

2 Likes

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 :stuck_out_tongue:

1 Like

Sir… You are awesome. It is working now. Just with a “.”. :slight_smile:

Can you please point me where it is written in the Go lang doc? I have missed it.

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. :smiley:

1 Like

I found the code. I should be more careful while reading the docs.

{{template "name" pipeline}}

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.