ExecuteTemplate (template.ParseGlob) loads Blank page - go

I'm trying to load template page.gohtml from folder cms/template. When trying to view in Firefox browser it load Blank.
handler.go file
var Tmpl = template.Must(template.ParseGlob("../templates/*"))
func ServeIndex(w http.ResponseWriter, r *http.Request) {
p := &Page{
Title: "Go Projects CMS",
Content: "Welcome to the Home Page!",
Posts: []*Post{
{
Title: "Hello World!",
Content: "Hey y'all, Thanks for coming",
DatePublished: time.Now(),
},
{
Title: "This Has Comments",
Content: "Atlassian Just Bought Trello...GO!",
DatePublished: time.Now().Add(-time.Hour),
Comments: []*Comment{
{
Author: "Davy Jones",
Content: "This is something to say about something",
DatePublished: time.Now().Add(-time.Hour / 2),
},
},
},
},
}
Tmpl.ExecuteTemplate(w, "page", p)
}
cmd/main.go file
func main() {
r := mux.NewRouter()
r.HandleFunc("/", cms.ServeIndex)
fmt.Println("Server running at port 3000")
go http.ListenAndServe(":3000", r)
fmt.Scanln()
}
templates/page.gohtml
{{ define "page" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ .Title }}</title>
<link rel="stylesheet" href="https://unpkg.com/tachyons#4.10.0/css/tachyons.min.css"/>
</head>
<body class="w-100 sans-serif bg-white">
<h1>Welcome</h1>
<div class="baskerville pb5">
{{ .Content }}
{{if .Posts}}
{{range .Posts}}
{{template "post" .}}
{{end}}
{{end}}
</div>
</body>
</html>
{{ end }}

I found the issue when I used error handling.
if err := Tmpl.ExecuteTemplate(w, "page", p); err != nil {
log.Printf("Template error: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
Which printed "no such template comments" while I was using defined "comment" inside comment.gohtml
Sorry for posting this question, I recently started GoLang.

Related

Prevent overwriting of blocks with same name in Go Template

I'm having difficulty in rendering the correct content using templates in Go. Either case of navigating to /about or / the same content is getting rendered. Below is the current state of code.
I have read that you can parse templates in each handleFunc (for each request) but that seems to be an inefficient way to mitigate the issue.
Code
I have the following templates
base
header
footer
index
about
{{ define "base"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Project Website</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css#2/out/water.css">
</head>
<body>
{{template "header" .}}
{{template "body" .}}
{{template "footer" .}}
</body>
</html>
{{end}}
{{define "header"}}
<h1>Header</h1>
{{end}}
{{define "footer"}}
<h1>Footer</h1>
{{end}}
{{template "base" .}}
{{define "body"}}
<h1>About</h1>
{{end}}
{{template "base" .}}
{{define "body"}}
<h1>Index</h1>
{{end}}
main.go
package main
import (
"html/template"
"log"
"net/http"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*"))
}
func main() {
// Connect to database.
// Routes
http.HandleFunc("/about", about)
http.HandleFunc("/", index)
http.HandleFunc("/favicon.ico", doNothing) // TODO Replace with something like do not found
// Listen and serve.
log.Fatal(http.ListenAndServe(":8000", nil))
}
// TODO go away
func doNothing(w http.ResponseWriter, r *http.Request) {}
handlerFunctions.go
package main
import (
"log"
"net/http"
)
func index(rw http.ResponseWriter, req *http.Request) {
log.Println("Index page called")
tpl.ExecuteTemplate(rw, "index.gohtml", nil)
}
func about(rw http.ResponseWriter, req *http.Request) {
log.Println("About page called")
tpl.ExecuteTemplate(rw, "about.gohtml", nil)
}

How to stream a PDF

I use Go and Gin for handle my web service. I want to stream a PDF file.
I tried to use html embed tag and pdf url for tag src, but this method not help me, because browser download the pdf.
For pdf handler I set content-type and someother headers but not work.
GO
func DownloadPdf(c *gin.Context) {
c.Writer.Header().Set("Content-type", "application/pdf")
c.FileAttachment(fmt.Sprintf("%s/order_%v.pdf", fileBasePath, myOrderUrl.OrderId), "bilit_pdf.pdf")
}
func LoadHtml(c *gin.Context) {
t, err := template.ParseFiles("Modules/Pdf/templates/pdf.gohtml")
if err != nil {
panic(err)
}
buf := new(bytes.Buffer)
if err = t.Execute(buf, "http://localhost:3001/v2/pdf/download/YfTgLuPPDc"); err != nil {
panic(err)
}
if _,err:=buf.WriteTo(c.Writer);err!=nil{
panic(err)
}
}
HTLM
<!DOCTYPE html>
<html lang="en" style="height: 100%;width: 100%">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 100%;width: 100%;margin: 0;overflow:hidden">
<embed
src="{{.}}"
type="application/pdf"
frameBorder="0"
height="100%"
width="100%">
</embed>
</body>
</html>
I found the answer with adding
c.Writer.Header().Set("Content-type", "application/octet-stream")
into my download code .
and opened PDF file when DownloadPdf route called .

How to set a variable for an external HTML template in Go?

I've two Go templates.
top.html:
<html>
<head>
<title>{{ .title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
</head>
<body>
and register.html:
{{ template "top.html" . }}
<h1>Register account</h1>
...
Currently to set the title I use the function:
r.GET("/register", func(c *gin.Context) {
c.HTML(http.StatusOK, "register.html", gin.H{
"title" : "Register Account"
})
})
This is not ideal as I have to set the parameter for every webpage. How can I set the title in top.html from register.html? I'd much rather have something that looks like:
{{ set .title = "Register Account" }}
{{ template "top.html" . }}
<h1>Register account</h1>
...
Of course, the above code does not work. Is there anything available to achieve what I want?
You can do this by implementing a template function. For example:
func mapset(m map[string]string, key, val string) error {
m[key] = val
return nil
}
Then, after registering it with the Funcs method, instead of {{ set .title = "Register Account" }} you would use it as:
{{ (mapset . "title" "Register Account") }}
https://play.golang.com/p/a08OVDpLLH4

Form Always Empty

I've been building a Go todo list and I'm trying to add the ability to add new items, but every time I access the form value, it comes out empty. Here's the handler I built:
func addHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
fmt.Print(err)
}
cook, _ := r.Cookie("userid")
id := cook.Value
r.ParseForm()
text := r.FormValue("todo")
addTodo(text,id) //inserts into database
http.Redirect(w,r,"/todo",http.StatusFound)
}
And here's the html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{{range .}}
<tr><td>{{printf "%s" .Text}}</td><td>delete</td></tr>
{{end}}
</table>
<form action="/add" method="post"><input type="text" name="todo"><button type="submit">Add</button></form>
</body>
</html>

How to render struct to html template?

i going to render html with data,when render,i don't know how to render struct of other file return for render on controller ,
code :
packages controller
type Index struct {
Title string
Body string
}
func IndexController(w http.ResponseWriter , r *http.Request){
if r.Method == "POST"{
data := &Index{
Title: "Hello",
Body: "Welcome to the WebGo.",
}
ff := renders.Sample{Temppath:"templates/index.tmpl",Data:data}
ff.Render(w)
my render package:
package renders
import (
"html/template"
"log"
"net/http"
)
type Sample struct {
Temppath string
Data struct{} ## i don't know how to use pass value of package controller to renders package ?
}
func (obj Sample) Render(w http.ResponseWriter) error {
var indexTemplate = template.Must(template.ParseFiles(obj.Temppath))
if err := indexTemplate.Execute(w, obj.Data); err != nil {
log.Println(err)
return err
}
return nil
}
html code :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/static/js/sample.js"></script>
<title>{{.Title}}</title>
<style>
body {
font-family: sans-serif;
}
h1 {
background: #ddd;
}
#sidebar {
float: right;
}
</style>
</head>
<body>
<h1>{{.Title}}</h1>
<div id="sidebar">
{{block "sidebar" .}}
<ul>
</ul>
{{end}}
</div>
{{block "content" .}}
<div id="content">
{{.Body}}
</div>
{{end}}
</body>
</html>
how to pass type Index struct to renders package for use indexTemplate.Execute(w, obj.Data)
Declare field Data in struct Sample as interface{}:
type Sample struct {
Temppath string
Data interface{}
}
The type Sample then can also be used in other controllers as placeholder of any data which is going to be passed to template.

Resources