Prevent overwriting of blocks with same name in Go Template - go

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

Related

How to Golang loop in html with http/template and net/http?

I am trying to handle data and then send it into html to be displayed in a specific field.
No expected output into {{.name}}. Works fine with {{.}}. No known structural wrongdoing.
Golang code
package main
import (
"fmt"
"html/template"
"net/http"
"github.com/gorilla/context"
)
var tpl *template.Template
func main() {
tpl, _ = template.ParseGlob("*.html")
http.HandleFunc("/test", testHandler)
http.ListenAndServe(":8080", context.ClearHandler(http.DefaultServeMux))
}
type Data struct {
allData []string
}
func testHandler(w http.ResponseWriter, r *http.Request) {
data := Data{allData: []string{"Add new", "jeff", "ffeej"}}
tpl.ExecuteTemplate(w, "test.html", data)
}
HTML code
<!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>test</title>
</head>
<body>
<section>
{{range .allData}}
{{.}}
{{end}}
</section>
</body>
</html>
How does one get the data out of the handler into the html in a specific wanted field?
What am I missing? I am still learning golang.
Thanks in advance.

Why does this request not POST?

There are many similar questions implemented in different stacks, but I have not found a useful answer. This code is modeled on many different tutorials, here is one: https://divyanshushekhar.com/golang-forms-data-request-body/
Pressing the button is supposed to submit the form so that the value of dataRequest can be used, however, it does not appear to post. Why?
<!DOCTYPE html>
<meta charset="utf-8" http-equiv="Content-Security-Policy" content="img-src * 'self' data: https:">
<head>
<title>Demo</title>
<link rel="icon" type="image/png" href="./favicon.ico">
</head>
<body style="background-color:#F0F8FF" style="font-size: 18px; font-family:verdana,arial,tahoma,serif;">
<form name="demoForm" style="background-color:#92a8d1">
<fieldset>
<input id="dataRequest" type="request" method="POST" value=""/>
<button type="submit" value="Run" />
</fieldset>
</form>
</body>
</html>
package main
import (
"fmt"
"net/http"
"log"
)
func index() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
http.ServeFile(w, r, "visible/index.html")
return
case "POST":
fmt.Println("Posted a request!")
err := r.ParseForm();
if err != nil {
log.Fatal(err)
}
request := r.Form.Get("dataRequest")
fmt.Println(request)
return
}
})
}
func main() {
mux := http.NewServeMux()
mux.Handle("/", index())
http.ListenAndServeTLS(":443", "./server.crt", "./server.key", mux)
}

Include css in html, where should I put the css file?

I am trying (unsuccessful) to include my css into my html. I have the files (executable, html and css)in the same directory "/test".
I have done some research over the subject but I can not still include the css in a proper way. For what I already saw if I include the css file starting with "/" it is relative to root folder so to confirm where is the root folder of the program I printed it and it is pointing to "C:\Users\Filipe\Desktop\go\src\test>" where are all my files.
test.go:
package main
import (
"fmt"
"net/http"
"os"
"text/template"
)
type Page struct {
Title string
NavItems []navItem
}
type navItem struct {
Item string
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
page := Page{
Title: "title",
NavItems: []navItem{
{Item: "item1"},
{Item: "item2"},
},
}
t, _ := template.ParseFiles("index.html")
t.Execute(w, page)
}
func testHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "/t directory test")
}
func main() {
http.HandleFunc("/", indexHandler)
fmt.Println(os.Getwd())
http.ListenAndServe(":8080", nil)
}
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="/mystyle.css">
<title>{{.Title}}</title>
</head>
<body>
<nav>
{{range .NavItems}}
<a>{{.Item}}<a>
{{end}}
</nav>
</body>
</html>
try to change -
<link rel="stylesheet" type="text/css" href="/mystyle.css">
to
<link rel="stylesheet" type="text/css" href="test/mystyle.css">
That will should solve the problem.

ExecuteTemplate (template.ParseGlob) loads Blank page

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.

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>

Resources