🐛 [Bug]: Template layout always show last loaded page.
jiuliyemingzhi opened this issue · 5 comments
Bug Description
Template layout always show last loaded page, I defined a layout template and some normal template they have similar struction.
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{.Title}}</title>
<link rel="stylesheet" type="text/css" href="all.min.css">
{{block "page-css" .}}{{end}}
</head>
<body>
{{block "main" .}}{{end}}
<script src="assets/js/all.min.js"></script>
{{block "page-js" .}}{{end}}
</body>
</html>
How to Reproduce
https://github.com/jiuliyemingzhi/fiber-tmpl-problem
1.go run main.go
2.click to open 127.0.0.1:3000 in browser
Expected Behavior
I think this page should show current url target page.
Template package Version
v2.1.1
Code Snippet (optional)
package main
import "github.com/gofiber/template/%package%"
func main() {
engine := html.New(conf.StaticPath, ".html")
engine.Debug(true)
engine.Reload(conf.Debug)
app := fiber.New(fiber.Config{
Views: engine,
BodyLimit: 2 * 1024 * 1024,
})
}
Checklist:
- I agree to follow Fiber's Code of Conduct.
- I have checked for existing issues that describe my problem prior to opening this one.
- I understand that improperly formatted bug reports may be closed without explanation.
pls use our layout approach with the {{embed}} tag
https://github.com/gofiber/template/tree/master/html#basic-example
@jiuliyemingzhi
pls use our layout approach with the {{embed}} tag https://github.com/gofiber/template/tree/master/html#basic-example @jiuliyemingzhi
Thinks,I know this but I have a more complex usage scenarios。So {{embed}} can't meet the demand。 Like this code
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{.Title}}</title>
<link rel="stylesheet" type="text/css" href="all.min.css">
{{block "page-css" .}}{{end}}
</head>
<body>
{{block "main" .}}{{end}}
<script src="assets/js/all.min.js"></script>
{{block "page-js" .}}{{end}}
</body>
</html>
To clarify. This is not a caching problem where the last rendered template is being re-rendered. The issue is that "main" has been redefined in various files in ./templates
, and all of them are being parsed by the views engine in app
.
For instance, I added a file to your example app:
I see two possible solutions to address the use case reported:
-
Use the
{{embed}}
tag to load different content in a layout with the FiberRender()
function. Define other dynamic, used in each template, content in go not the html templates. -
Use
html/template
independently of Fiber to limit which file is parsed by the template, which will be slower without caching etc, but prevents "main" from being redefined by other files.
Example for solution 2:
package main
import (
"bytes"
"html/template"
"log"
"path/filepath"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New(fiber.Config{})
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.Redirect("/index2.html")
})
app.Get("/:page", func(ctx *fiber.Ctx) error {
page := ctx.Params("page", "index1.thml")
// Clean the page parameter and join it with the template directory
pagePath := filepath.Join("template", filepath.Clean("/"+page))
tmpl, err := template.ParseFiles("template/layout.html", pagePath)
if err != nil {
return ctx.Status(404).SendString("404 Not Found")
}
var buf bytes.Buffer
err = tmpl.Execute(&buf, map[string]interface{}{})
if err != nil {
log.Println("Template execution error:", err)
return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
}
ctx.Response().Header.SetContentType(fiber.MIMETextHTMLCharsetUTF8)
return ctx.Status(fiber.StatusOK).Send(buf.Bytes())
})
log.Fatal(app.Listen(":3000"))
}
@jiuliyemingzhi hope that helps.
@ReneWerner87, I think that this is not a bug, but rather an implementation detail that reflects the behaviour of the html/template
ParseFiles()
function. To avoid confusion, it would be helpful to update the documentation to explain that templates read during Load()
are loaded when the app is initialized, and the use case mentioned by @jiuliyemingzhi is not supported.
To clarify. This is not a caching problem where the last rendered template is being re-rendered. The issue is that "main" has been redefined in various files in
./templates
, and all of them are being parsed by the views engine inapp
.For instance, I added a file to your example app:
I see two possible solutions to address the use case reported:
- Use the
{{embed}}
tag to load different content in a layout with the FiberRender()
function. Define other dynamic, used in each template, content in go not the html templates.- Use
html/template
independently of Fiber to limit which file is parsed by the template, which will be slower without caching etc, but prevents "main" from being redefined by other files.Example for solution 2:
package main import ( "bytes" "html/template" "log" "path/filepath" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New(fiber.Config{}) app.Get("/", func(ctx *fiber.Ctx) error { return ctx.Redirect("/index2.html") }) app.Get("/:page", func(ctx *fiber.Ctx) error { page := ctx.Params("page", "index1.thml") // Clean the page parameter and join it with the template directory pagePath := filepath.Join("template", filepath.Clean("/"+page)) tmpl, err := template.ParseFiles("template/layout.html", pagePath) if err != nil { return ctx.Status(404).SendString("404 Not Found") } var buf bytes.Buffer err = tmpl.Execute(&buf, map[string]interface{}{}) if err != nil { log.Println("Template execution error:", err) return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") } ctx.Response().Header.SetContentType(fiber.MIMETextHTMLCharsetUTF8) return ctx.Status(fiber.StatusOK).Send(buf.Bytes()) }) log.Fatal(app.Listen(":3000")) }@jiuliyemingzhi hope that helps.
@ReneWerner87, I think that this is not a bug, but rather an implementation detail that reflects the behaviour of the
html/template
ParseFiles()
function. To avoid confusion, it would be helpful to update the documentation to explain that templates read duringLoad()
are loaded when the app is initialized, and the use case mentioned by @jiuliyemingzhi is not supported.
Thanks! That solved my problem.
Yes right, the engine loads all files and renders them and then definitions with the same names are overwritten
That was the reason why I meant the embed layout
But right, with more explanations it offers more acceptance
Thx @sixcolors for the explanation