Ben
Ben

Reputation: 11

Go template ranging over struct of structs

I'm attempting to range over a list of a struct consisting of 2 structs inside of it. I have no problem filling the data correctly in the struct, the problem is when I try to render it into the HTML. I can't get anything to display.

This is my first go web project and I'm working on a website to sell cars for a small business. My Database is designed as a 1..M of Cars to Pics. So on the main car page. I want to just load 1 pic with the details of the car. I tried using a map for this but I ran into an issue when I wanted to print out just 1 picture to go with the correct car details on the common ID. So I figured using a third struct that I pull out one pic for each ID would work.

type Car struct {
    Id int
    Year, Make, Model, Price string
}

type Pics struct {
    Id int
    Path string
}


type CarDetail struct {
    Cars Car
    Pic Pics
}

func cars(w http.ResponseWriter, r *http.Request){
  //loads all the cars in the database
  cars := loadCars()
  carDetails := make([]CarDetail,0)
  carIds := make([]int,len(cars))
  for i := 0; i < len(cars); i++{
    //gets all the car IDs in the db
    carIds[i] = getCarID(cars[i]) 
    photoPath := loadSinglePhoto(carIds[i]) //now have the single photo
    n := CarDetail{Cars:cars[i],Pic:photoPath}
    carDetails = append(carDetails, n)
}

fmt.Println(carDetails) //getting car details the way I want
tpl.ExecuteTemplate(w, "cars", &carDetails)
}

The print statement right before I pass in the struct gives me the information the way I intended.

[{{20 2009 Honda Accord 5000} {20 public/pics/questionMark.jpg}} {{21 2009 Acura TLX 14000} {21 public/pics/kia.png}} {{22 2015 Kia Sportage 34000} {22 public/pics/kia.png}}]

Now when I try to render it in the html

{{range .}}
  <h3>{{.Cars.Make}} - {{.Cars.Model}} - {{.Cars.Year}}</h3>
  <img src="{{.Pic.Path}}" id="{{.Pic.Id}}">
{{end}}

Feel free to be critical of my code or suggest another way. Thank you in advance!

Upvotes: 0

Views: 5383

Answers (2)

Ben
Ben

Reputation: 11

So I found the culprit. Strangely enough some commented out HTML code from earlier was causing the template not to be rendered. I'm not sure why.

<!--

<h1>Your Pictures:</h1>
{{range .Pics}}
<img class="insertedPics" src="{{.Path}}" alt="pic" id="{{.Id}}" 
height="500px" width="500px">
{{end}}

{{range .Cars}}
<h3>{{.Make}} - {{.Model}} - {{.Year}} </h3>
{{end}}

<img src="{{.Pic.Path}}" alt="car pic" id="{{.Car.Id}}" height="600px" width="600px">

-->        <-- Once I removed this, everything worked fine.

{{range .}}
<h3>{{.C.Make}} - {{.C.Model}}</h3>
<img src="{{.P.Path}}" alt="some pic" height="500px" width="500px" 
style="">
{{end}}

Thank you for the help and suggestions!

Upvotes: 1

mhcbinder
mhcbinder

Reputation: 49

Some remarks on a general level:

  • Your naming is a bit misleading: Pics holds only a single picture, not many (not an array or map); same applies to CarDetail.Cars
  • Not knowing which database you are using I would recommend to build a query returning both cars and (primary) picture, as looking the pics up by every single car will not perform well
  • I would recommend storing the templates as files in a sub-folder with specific extensions (e.g. "cars.gohtml") and then use template.ParseGlob("templates/*.gohtml")

Apart from that it should work, see a slightly refactored working example here: https://play.golang.org/p/CPnad9FxaB

So what exactly is going wrong in your own code?

Upvotes: 1

Related Questions