Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨feature: Pass all locals to ctx.Render #1693

Merged
merged 5 commits into from Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions app.go
Expand Up @@ -183,6 +183,11 @@ type Config struct {
// Default: ""
ViewsLayout string `json:"views_layout"`

// PassLocalsToViews Enables passing of the locals set on a fiber.Ctx to the template engine
kingdevnl marked this conversation as resolved.
Show resolved Hide resolved
//
// Default: false
PassLocalsToViews bool `json:"pass_locals_to_views"`

// The amount of time allowed to read the full request including body.
// It is reset after the request handler has returned.
// The connection's read deadline is reset when the connection opens.
Expand Down
20 changes: 20 additions & 0 deletions ctx.go
Expand Up @@ -1017,6 +1017,26 @@ func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error {
buf := bytebufferpool.Get()
defer bytebufferpool.Put(buf)

// Check if the PassLocalsToViews option is enabled (By default it is disabled)
if c.app.config.PassLocalsToViews {
// Safely cast the bind interface to a map
bindMap, ok := bind.(Map)
// Check if the bind is a map
if ok {
// Loop through each local and set it in the map
c.fasthttp.VisitUserValues(func(key []byte, val interface{}) {
// check if bindMap doesn't contain the key
if _, ok := bindMap[string(key)]; !ok {
// Set the key and value in the bindMap
bindMap[string(key)] = val
}
})
// set the original bind to the map
bind = bindMap
}

}

if c.app.config.Views != nil {
// Render template based on global layout if exists
if len(layouts) == 0 && c.app.config.ViewsLayout != "" {
Expand Down
58 changes: 58 additions & 0 deletions ctx_test.go
Expand Up @@ -2006,6 +2006,64 @@ func Test_Ctx_Render(t *testing.T) {
err = c.Render("./.github/testdata/template-invalid.html", nil)
utils.AssertEqual(t, false, err == nil)
}
func Test_Ctx_RenderWithoutLocals(t *testing.T) {
t.Parallel()
app := New(Config{
PassLocalsToViews: false,
})
c := app.AcquireCtx(&fasthttp.RequestCtx{})

c.Locals("Title", "Hello, World!")
defer app.ReleaseCtx(c)
err := c.Render("./.github/testdata/template.html", Map{})

buf := bytebufferpool.Get()
_, _ = buf.WriteString("overwrite")
defer bytebufferpool.Put(buf)

utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "<h1><no value></h1>", string(c.Response().Body()))
}

func Test_Ctx_RenderWithLocals(t *testing.T) {
t.Parallel()
app := New(Config{
PassLocalsToViews: true,
})
c := app.AcquireCtx(&fasthttp.RequestCtx{})

c.Locals("Title", "Hello, World!")
defer app.ReleaseCtx(c)
err := c.Render("./.github/testdata/template.html", Map{})

buf := bytebufferpool.Get()
_, _ = buf.WriteString("overwrite")
defer bytebufferpool.Put(buf)

utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "<h1>Hello, World!</h1>", string(c.Response().Body()))

}
func Test_Ctx_RenderWithLocalsAndBinding(t *testing.T) {
t.Parallel()
app := New(Config{
PassLocalsToViews: true,
})
c := app.AcquireCtx(&fasthttp.RequestCtx{})

c.Locals("Title", "This is a test.")
defer app.ReleaseCtx(c)
err := c.Render("./.github/testdata/template.html", Map{
"Title": "Hello, World!",
})

buf := bytebufferpool.Get()
_, _ = buf.WriteString("overwrite")
defer bytebufferpool.Put(buf)

utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "<h1>Hello, World!</h1>", string(c.Response().Body()))
}

type testTemplateEngine struct {
templates *template.Template
Expand Down