mirror of
https://github.com/kataras/iris.git
synced 2025-03-14 08:26:26 +01:00
context.ViewData(key,value) and ViewLayout(layout) http://support.iris-go.com/d/27-using-middleware-to-inject-properties-for-templates/3
Nothing that you couldn't do before. Former-commit-id: 658ec25d8045d25a76f87c8f992e67e64006e287
This commit is contained in:
parent
126c4de29b
commit
57576c70cb
12
HISTORY.md
12
HISTORY.md
|
@ -8,13 +8,21 @@
|
|||
|
||||
|
||||
## 6.1.4 -> 6.2.0 (√Νεxτ)
|
||||
|
||||
|
||||
_Update: 28 March 2017_
|
||||
|
||||
- **View**: Provide an easier method on the community's question about "injecting" additional data outside of the route's main handler which calls the .Render, via middleware.
|
||||
- As discussed [above](http://support.iris-go.com/d/27-using-middleware-to-inject-properties-for-templates).
|
||||
- Click [here](https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data) for an example.
|
||||
|
||||
_Update: 18 March 2017_
|
||||
|
||||
- **Sessions**: Enchance the community feature request about custom encode and decode methods for the cookie value(sessionid) as requested [here](http://support.iris-go.com/d/29-mark-cookie-for-session-as-secure).
|
||||
- **Sessions**: Enchance the community's feature request about custom encode and decode methods for the cookie value(sessionid) as requested [here](http://support.iris-go.com/d/29-mark-cookie-for-session-as-secure).
|
||||
|
||||
_Update: 12 March 2017_
|
||||
|
||||
- Enhance Custom http errors with gzip and static files handler, as requested/reported [here](http://support.iris-go.com/d/17-fallback-handler-for-non-matched-routes/9).
|
||||
- Enhance Custom http errors with gzip and static files handler, as requested/reported [here](http://support.iris-go.com/d/17-fallback-handler-for-non-matched-routes).
|
||||
- Enhance per-party custom http errors (now it works on any wildcard path too).
|
||||
- Add a third parameter on `app.OnError(...)` for custom http errors with regexp validation, see [status_test.go](https://github.com/kataras/iris/blob/v6/status_test.go) for an example.
|
||||
- Add a `context.ParamIntWildcard(...)` to skip the first slash, useful for wildcarded paths' parameters.
|
||||
|
|
70
README.md
70
README.md
|
@ -129,6 +129,76 @@ Feature Overview
|
|||
- Feels like you used iris forever, thanks to its Fluent API
|
||||
- And many others...
|
||||
|
||||
|
||||
Table of Contents
|
||||
-----------
|
||||
|
||||
<img align="right" src="http://iris-go.com/assets/book/cover_4.jpg" width="300" />
|
||||
|
||||
* [Level: Beginner](_examples/beginner)
|
||||
* [Hello World](_examples/beginner/hello-world/main.go)
|
||||
* [Routes (using httprouter)](_examples/beginner/routes-using-httprouter/main.go)
|
||||
* [Routes (using gorillamux)](_examples/beginner/routes-using-gorillamux/main.go)
|
||||
* [Internal Application File Logger](_examples/beginner/file-logger/main.go)
|
||||
* [Write JSON](_examples/beginner/write-json/main.go)
|
||||
* [Read JSON](_examples/beginner/read-json/main.go)
|
||||
* [Read Form](_examples/beginner/read-form/main.go)
|
||||
* [Favicon](_examples/beginner/favicon/main.go)
|
||||
* [File Server](_examples/beginner/file-server/main.go)
|
||||
* [Send Files](_examples/beginner/send-files/main.go)
|
||||
* [Stream Writer](_examples/beginner/stream-writer/main.go)
|
||||
* [Listen UNIX Socket](_examples/beginner/listen-unix/main.go)
|
||||
* [Listen TLS](_examples/beginner/listen-tls/main.go)
|
||||
* [Listen Letsencrypt (Automatic Certifications)](_examples/beginner/listen-letsencrypt/main.go)
|
||||
* [Level: Intermediate](_examples/intermediate)
|
||||
* [Send An E-mail](_examples/intermediate/e-mail/main.go)
|
||||
* [Upload/Read Files](_examples/intermediate/upload-files/main.go)
|
||||
* [Request Logger](_examples/intermediate/request-logger/main.go)
|
||||
* [Profiling (pprof)](_examples/intermediate/pprof/main.go)
|
||||
* [Basic Authentication](_examples/intermediate/basicauth/main.go)
|
||||
* [HTTP Access Control](_examples/intermediate/cors/main.go)
|
||||
* [Cache Markdown](_examples/intermediate/cache-markdown/main.go)
|
||||
* [Localization and Internationalization](_examples/intermediate/i18n/main.go)
|
||||
* [Recovery](_examples/intermediate/recover/main.go)
|
||||
* [Graceful Shutdown](_examples/intermediate/graceful-shutdown/main.go)
|
||||
* [Custom TCP Listener](_examples/intermediate/custom-listener/main.go)
|
||||
* [Custom HTTP Server](_examples/intermediate/custom-httpserver/main.go)
|
||||
* [View Engine](_examples/intermediate/view)
|
||||
* [Overview](_examples/intermediate/view/overview/main.go)
|
||||
* [Template HTML: Part Zero](_examples/intermediate/view/template_html_0/main.go)
|
||||
* [Template HTML: Part One](_examples/intermediate/view/template_html_1/main.go)
|
||||
* [Template HTML: Part Two](_examples/intermediate/view/template_html_2/main.go)
|
||||
* [Template HTML: Part Three](_examples/intermediate/view/template_html_3/main.go)
|
||||
* [Template HTML: Part Four](_examples/intermediate/view/template_html_4/main.go)
|
||||
* [Inject Data Between Handlers](_examples/intermediate/view/context-view-data/main.go)
|
||||
* [Embedding Templates Into Executable](_examples/intermediate/embedding-templates-into-app)
|
||||
* [Custom Renderer](_examples/intermediate/view/custom-renderer/main.go)
|
||||
* [Password Hashing](_examples/intermediate/password-hashing/main.go)
|
||||
* [Sessions](_examples/intermediate/sessions)
|
||||
* [Overview](_examples/intermediate/sessions/overview/main.go)
|
||||
* [Encoding & Decoding the Session ID: Secure Cookie](_examples/intermediate/sessions/securecookie/main.go)
|
||||
* [Standalone](_examples/intermediate/sessions/standalone/main.go)
|
||||
* [With A Back-End Database](_examples/intermediate/sessions/database/main.go)
|
||||
* [Flash Messages](_examples/intermediate/flash-messages/main.go)
|
||||
* [Websockets](_examples/intermediate/websockets)
|
||||
* [Ridiculous Simple](_examples/intermediate/websockets/ridiculous-simple/main.go)
|
||||
* [Overview](_examples/intermediate/websockets/overview/main.go)
|
||||
* [Connection List](_examples/intermediate/websockets/connectionlist/main.go)
|
||||
* [Native Messages](_examples/intermediate/websockets/naive-messages/main.go)
|
||||
* [Secure](_examples/intermediate/websockets/secure/main.go)
|
||||
* [Custom Go Client](_examples/intermediate/websockets/custom-go-client/main.go)
|
||||
* [Level: Advanced](_examples/advanced)
|
||||
* [Transactions](_examples/advanced/transactions/main.go)
|
||||
* [HTTP Testing](_examples/advanced/httptest/main_test.go)
|
||||
* [Watch & Compile Typescript source files](_examples/advanced/typescript/main.go)
|
||||
* [Cloud Editor](_examples/advanced/cloud-editor/main.go)
|
||||
* [Online Visitors](_examples/advanced/online-visitors/main.go)
|
||||
* [URL Shortener using BoltDB](_examples/advanced/url-shortener/main.go)
|
||||
* [Subdomains](_examples/advanced/subdomains)
|
||||
* [Single](_examples/advanced/subdomains/single/main.go)
|
||||
* [Multi](_examples/advanced/subdomains/multi/main.go)
|
||||
* [Wildcard](_examples/advanced/subdomains/wildcard/main.go)
|
||||
|
||||
Installation
|
||||
-----------
|
||||
|
||||
|
|
|
@ -38,12 +38,13 @@ It doesn't contains "best ways" neither explains all its features. It's just a s
|
|||
* [Custom HTTP Server](intermediate/custom-httpserver/main.go)
|
||||
* [View Engine](intermediate/view)
|
||||
* [Overview](intermediate/view/overview/main.go)
|
||||
* [Embedding Templates Into Executable](intermediate/embedding-templates-into-app)
|
||||
* [Template HTML: Part Zero](intermediate/view/template_html_0/main.go)
|
||||
* [Template HTML: Part One](intermediate/view/template_html_1/main.go)
|
||||
* [Template HTML: Part Two](intermediate/view/template_html_2/main.go)
|
||||
* [Template HTML: Part Three](intermediate/view/template_html_3/main.go)
|
||||
* [Template HTML: Part Four](intermediate/view/template_html_4/main.go)
|
||||
* [Inject Data Between Handlers](intermediate/view/context-view-data/main.go)
|
||||
* [Embedding Templates Into Executable](intermediate/embedding-templates-into-app)
|
||||
* [Custom Renderer](intermediate/view/custom-renderer/main.go)
|
||||
* [Password Hashing](intermediate/password-hashing/main.go)
|
||||
* [Sessions](intermediate/sessions)
|
||||
|
|
58
_examples/intermediate/view/context-view-data/main.go
Normal file
58
_examples/intermediate/view/context-view-data/main.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
// this example will show you how you can set per-request data for a template outside of the main handler which calls
|
||||
// the .Render, via middleware.
|
||||
//
|
||||
// Remember: .Render has the "binding" argument which can be used to send data to the template at any case.
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultTitle = "My Awesome Site"
|
||||
DefaultLayout = "layouts/layout.html"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
app.Adapt(iris.DevLogger())
|
||||
// set the router, you can choose gorillamux too
|
||||
app.Adapt(httprouter.New())
|
||||
// set the view engine target to ./templates folder
|
||||
app.Adapt(view.HTML("./templates", ".html").Reload(true))
|
||||
|
||||
app.UseFunc(func(ctx *iris.Context) {
|
||||
// set the title, current time and a layout in order to be used if and when the next handler(s) calls the .Render function
|
||||
ctx.ViewData("Title", DefaultTitle)
|
||||
now := time.Now().Format(app.Config.TimeFormat)
|
||||
ctx.ViewData("CurrentTime", now)
|
||||
ctx.ViewLayout(DefaultLayout)
|
||||
|
||||
ctx.Next()
|
||||
})
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.ViewData("BodyMessage", "a sample text here... setted by the route handler")
|
||||
if err := ctx.Render("index.html", nil); err != nil {
|
||||
app.Log(iris.DevMode, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
app.Get("/about", func(ctx *iris.Context) {
|
||||
ctx.ViewData("Title", "My About Page")
|
||||
ctx.ViewData("BodyMessage", "about text here... setted by the route handler")
|
||||
|
||||
// same file, just to keep things simple.
|
||||
if err := ctx.Render("index.html", nil); err != nil {
|
||||
app.Log(iris.DevMode, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
// Open localhost:8080 and localhost:8080/about
|
||||
app.Listen(":8080")
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<h1>
|
||||
Title: {{.Title}}
|
||||
</h1>
|
||||
<h3>{{.BodyMessage}} </h3>
|
||||
|
||||
<hr/>
|
||||
|
||||
Current time: {{.CurrentTime}}
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>My WebsiteLayout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
113
context.go
113
context.go
|
@ -869,13 +869,6 @@ func (ctx *Context) TryWriteGzip(b []byte) (int, error) {
|
|||
// -------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
const (
|
||||
// NoLayout to disable layout for a particular template file
|
||||
NoLayout = "@.|.@no_layout@.|.@"
|
||||
// TemplateLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
|
||||
TemplateLayoutContextKey = "templateLayout"
|
||||
)
|
||||
|
||||
// getGzipOption receives a default value and the render options map and returns if gzip is enabled for this render action
|
||||
func getGzipOption(defaultValue bool, options map[string]interface{}) bool {
|
||||
gzipOpt := options["gzip"] // we only need that, so don't create new map to keep the options.
|
||||
|
@ -933,8 +926,66 @@ func (ctx *Context) fastRenderWithStatus(status int, cType string, data []byte)
|
|||
return
|
||||
}
|
||||
|
||||
const (
|
||||
// NoLayout to disable layout for a particular template file
|
||||
NoLayout = "@.|.@no_layout@.|.@"
|
||||
// ViewLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
|
||||
ViewLayoutContextKey = "@viewLayout"
|
||||
ViewDataContextKey = "@viewData"
|
||||
|
||||
// conversions
|
||||
// TemplateLayoutContextKey same as ViewLayoutContextKey
|
||||
TemplateLayoutContextKey = ViewLayoutContextKey
|
||||
)
|
||||
|
||||
// ViewLayout sets the "layout" option if and when .Render
|
||||
// is being called afterwards, in the same request.
|
||||
// Useful when need to set or/and change a layout based on the previous handlers in the chain.
|
||||
//
|
||||
// Look: .ViewData | .Render
|
||||
// .MustRender | .RenderWithStatus also.
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data/
|
||||
func (ctx *Context) ViewLayout(layoutTmplFile string) {
|
||||
ctx.Set(ViewLayoutContextKey, layoutTmplFile)
|
||||
}
|
||||
|
||||
// ViewData saves one or more key-value pair in order to be passed if and when .Render
|
||||
// is being called afterwards, in the same request.
|
||||
// Useful when need to set or/and change template data from previous hanadlers in the chain.
|
||||
//
|
||||
// If .Render's "binding" argument is not nil and it's not a type of map
|
||||
// then these data are being ignored, binding has the priority, so the main route's handler can still decide.
|
||||
// If binding is a map or iris.Map then theese data are being added to the view data
|
||||
// and passed to the template.
|
||||
//
|
||||
// After .Render, the data are not destroyed, in order to be re-used if needed (again, in the same request as everything else),
|
||||
// to manually clear the view data, developers can call:
|
||||
// ctx.Set(iris.ViewDataContextKey, iris.Map{})
|
||||
//
|
||||
// Look: .ViewLayout | .Render
|
||||
// .MustRender | .RenderWithStatus also.
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data/
|
||||
func (ctx *Context) ViewData(key string, value interface{}) {
|
||||
v := ctx.Get(ViewDataContextKey)
|
||||
if v == nil {
|
||||
ctx.Set(ViewDataContextKey, Map{key: value})
|
||||
return
|
||||
}
|
||||
|
||||
if data, ok := v.(Map); ok {
|
||||
data[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// RenderWithStatus builds up the response from the specified template or a serialize engine.
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engines
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engines.
|
||||
//
|
||||
// Look: .ViewData | .Render
|
||||
// .ViewLayout | .MustRender also.
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
|
||||
func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) (err error) {
|
||||
if _, shouldFirstStatusCode := ctx.ResponseWriter.(*responseWriter); shouldFirstStatusCode {
|
||||
ctx.SetStatusCode(status)
|
||||
|
@ -957,6 +1008,38 @@ func (ctx *Context) RenderWithStatus(status int, name string, binding interface{
|
|||
}
|
||||
}
|
||||
|
||||
// optional, view data (useful for middleware, although user can already do that with ctx.Set/Get)
|
||||
// check if user sets any view data
|
||||
if v := ctx.Get(ViewDataContextKey); v != nil {
|
||||
// if so, then check its type, to make sure
|
||||
if data, ok := ctx.Get(ViewDataContextKey).(Map); ok {
|
||||
if len(data) > 0 {
|
||||
if binding != nil {
|
||||
// if binding is passed to the Render function then
|
||||
// two things can happen:
|
||||
// if binding is a custom type, we ignore the data
|
||||
// if binding is a map of interface{} or string then, add these to the view data
|
||||
// finally, set the binding to the new data and pass it to the view engine, as we did before.
|
||||
|
||||
if irisMap, ok := binding.(Map); ok {
|
||||
for key, val := range irisMap {
|
||||
data[key] = val
|
||||
} // a little of necessary duplication here...
|
||||
} else if stdMap, ok := binding.(map[string]interface{}); ok {
|
||||
for key, val := range stdMap {
|
||||
data[key] = val
|
||||
}
|
||||
} else if stdMapStr, ok := binding.(map[string]string); ok {
|
||||
for key, val := range stdMapStr {
|
||||
data[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
binding = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find Content type
|
||||
// if it the name is not a template file, then take that as the content type.
|
||||
cType := contentHTML
|
||||
|
@ -999,7 +1082,12 @@ func (ctx *Context) RenderWithStatus(status int, name string, binding interface{
|
|||
|
||||
// Render same as .RenderWithStatus but with status to iris.StatusOK (200) if no previous status exists
|
||||
// builds up the response from the specified template or a serialize engine.
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine.
|
||||
//
|
||||
// Look: .ViewData | .MustRender
|
||||
// .ViewLayout | .RenderWithStatus also.
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
|
||||
func (ctx *Context) Render(name string, binding interface{}, options ...map[string]interface{}) error {
|
||||
errCode := ctx.ResponseWriter.StatusCode()
|
||||
if errCode <= 0 {
|
||||
|
@ -1009,7 +1097,12 @@ func (ctx *Context) Render(name string, binding interface{}, options ...map[stri
|
|||
}
|
||||
|
||||
// MustRender same as .Render but returns 503 service unavailable http status with a (html) message if render failed
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine
|
||||
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine.
|
||||
//
|
||||
// Look: .ViewData | .Render
|
||||
// .ViewLayout | .RenderWithStatus also.
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
|
||||
func (ctx *Context) MustRender(name string, binding interface{}, options ...map[string]interface{}) {
|
||||
if err := ctx.Render(name, binding, options...); err != nil {
|
||||
htmlErr := ctx.HTML(StatusServiceUnavailable,
|
||||
|
|
Loading…
Reference in New Issue
Block a user