I've recently changed the file structure of my project and now I cannot seem to get my html files to load properly.
I have followed the advice of a couple of different answers on this similar topic to no avail.
In regards to file structure, getIndexPageHandler
is in src/controllers/index.go
and index.html
is in src/views/index.html
Also, when I use fmt.Println(filepath.Join(cwd, "./views/index.html"))
it returns C:\Projects\Go\src\views\index.html
This confuses me, that's the direct path of the file so why is it telling me that index.html cannot be found whenever I try to navigate to it? Also I didn't post the router that calls this on the /index
route but this exact block of code worked before when the html files were in the same directory as my controller files so I believe the error is in this block.
func getIndexPageHandler(w http.ResponseWriter, r *http.Request) {
cwd, err := os.Getwd()
utils.CheckErr(err)
template, err := template.ParseFiles(filepath.Join(cwd, "./views/index.html"), filepath.Join(cwd, "./views/header.html"))
utils.CheckErr(err)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
err = template.ExecuteTemplate(w, filepath.Join(cwd, "./views/index.html"), nil)
utils.CheckErr(err)
}
The first part of the problem is that you're using ParseFiles
, which uses the base name of the first file to set the returned *template.Template
's name.
From the docs:
ParseFiles creates a new Template and parses the template definitions from the named files. The returned template's name will have the (base) name and (parsed) contents of the first file.
The second part is that you're using ExecuteTemplate
passing the full path as the second argument while the docs say that its second argument should be the name of the template to execute.
the docs:
ExecuteTemplate applies the template associated with t that has the given name to the specified data object and writes the output to wr.
Couple ways to fix this:
// the name of t becomes the base of first file, which is "index.html"
t, err := template.ParseFiles(filepath.Join(cwd, "./views/index.html"), filepath.Join(cwd, "./views/header.html"))
utils.CheckErr(err)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// use the base name of the first file from ParseFiles
err = t.ExecuteTemplate(w, "index.html", nil)
utils.CheckErr(err)
Or
// specify desired name using New
t, err := template.New("my_template").ParseFiles(filepath.Join(cwd, "./views/index.html"), filepath.Join(cwd, "./views/header.html"))
utils.CheckErr(err)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// use the name specified with New
err = t.ExecuteTemplate(w, "my_template", nil)
utils.CheckErr(err)
Or
// don't care about name because we'll use Execute instead of ExecuteTemplate
t, err := template.ParseFiles(filepath.Join(cwd, "./views/index.html"), filepath.Join(cwd, "./views/header.html"))
utils.CheckErr(err)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// call Execute
err = t.Execute(w, nil)
utils.CheckErr(err)
Read more:
You need to use two dots, for one directory up.
"../views/index.html"