Reputation: 14874
I am new to go and have difficulty rendring templates.
Here is my functions that are to generate template:
base.html
//Render templates for the given name, template definition and data object
func renderTemplate(w http.ResponseWriter, name string, template string, viewModel interface{}) {
// Ensure the template exists in the map.
tmpl, ok := templates[name]
if !ok {
http.Error(w, "The template does not exist.", http.StatusInternalServerError)
}
err := tmpl.ExecuteTemplate(w, template, viewModel)
if err != nil {
log.Printf("temlate error here")
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func EditNote(w http.ResponseWriter, r *http.Request) {
//var viewModel models.EditChnl
vars := mux.Vars(r)
//ch := bson.M{"id": "Ale"}
title := vars["title"]
log.Printf("%v\n", title)
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("tlgdb").C("chnls")
log.Printf("title is %s \n", title)
var result []models.Chnl
err = c.Find(bson.M{"title": "xxx"}).All(&result)
log.Printf("%v\n", result)
if err != nil {
log.Printf("doc not found")
log.Fatal(err)
return
}
renderTemplate(w, "edit", "base", result)
}
And here are the templates:
{{define "base"}}
<html>
<head>
{{template "head" .}}
</head>
<body>
{{template "body" .}}
</body>
</html>
{{end}}
edit.thml
{{define "head"}}<title>Edit Note</title>{{end}}
{{define "body"}}
<h1>Edit Note</h1>
<form action="/chnls/update/{{.Title}}" method="post">
<p>Title:<br> <input type="text" value="{{.Title}}" name="title"></p>
<p>Description:<br> <textarea rows="4" cols="50" name="description">{{.Description}}</textarea> </p>
<p><input type="submit" value="submit"/></p>
</form>
{{end}}
The objects to render are:
type Chnl struct {
Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
Title string
Description string
CreatedOn time.Time
Creator string
Visits int
Score int
}
The object that I'm trying to render exists in mongodb and I can print it out in console:
[{ObjectIdHex("56cc4493bc54f4245cb4d36b") sometitle blabla 2016-02-23 12:37:55.972 +0100 CET blabla 0 0}]
However I get this error:
temlate error here
http: multiple response.WriteHeader calls
I'm wondering what is wrong here and how to fix it?
Upvotes: 2
Views: 1138
Reputation: 418585
The root problem is that you pass a slice of Chnl
to the template:
var result []models.Chnl
// ...
renderTemplate(w, "edit", "base", result)
And inside renderTemplate()
param value of viewModel
will be result
.
And in your templates you refer to fields of the dot like if it would be a Chnl
value and not a slice of it: {{.Title}}
. So the first attempt to resolve it will fail.
Logging the errors is useful, so change your logging to also print the actual error, not just a generic error:
log.Printf("Temlate error here: %v", err)
Which results in:
2016/02/24 14:57:09 Temlate error here: template: edit.html:4:30: executing "body" at <.Title>: can't evaluate field Title in type []main.Chnl
I think you just want to pass 1 Chnl
value and not a slice of them. In EditNote()
:
if len(result) > 0 {
renderTemplate(w, "edit", "base", result[0])
}
Next, know that http.Error()
writes content to the response. This means you cannot write further header values to the response. Usually when you call http.Error()
in your handler, you should return without doing anything with the response:
if !ok {
http.Error(w, "The template does not exist.", http.StatusInternalServerError)
return // NOTE THIS RETURN
}
Similarly, after all your http.Error()
call insert a return
. You may do some cleanup, but response should not be touched after http.Error()
.
Upvotes: 2