Skip to content

Commit

Permalink
✨feature: Pass all locals to ctx.Render (#1693)
Browse files Browse the repository at this point in the history
* ✨feature: Pass all locals to ctx.Render

* add test case for render using locals

* Added option PassLocalsToViews to enable pass locals to render

The option PassLocalsToViews is set to disabled by default

* Added a check to see if the ctx bind already contains the value

* Added a test for ctx render with locals and binds.
  • Loading branch information
kingdevnl committed Jan 24, 2022
1 parent d59f1af commit 82d1039
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
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
//
// 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

0 comments on commit 82d1039

Please sign in to comment.