Implementing custom filters in Revel

In my project, I wanted that if a user is on the login page of my application, he should see Signup button in the top left corner of the page, and if the user was on signup page, I wanted to show login button in its place. Fairly standard functionality, all I needed was controller and action names to be accessible in my template.

Boom! I realised, there was no “builtin” way of doing it in revel. There was no variable like {{.controller}} or {{.action}} which I could access in html template to check.

Since, accessing controller and action name in a template is fairly standard way of doing things (atleast for me), I decided to implement a filter which would pass controller and action to template.

To implement a filter in Revel, We need to define our custom filter in init.go file (in /app folder) on following lines

var MyFilter = func(c *revel.Controller, fc []revel.Filter) {
	// .. do some pre-processing ..
	controller := c.Name
	action := c.Action
	c.RenderArgs["controller"] = controller
	c.RenderArgs["action"] = action

	fc[0](c, fc[1:]) // Execute the next filter stage.

	// .. do some post-processing ..
}

In the above code we use RenderArgs to render name of controller and action for every controller.

Now we only need to add this filter to our filter chain, which can be done by updating revel.Filters variable

revel.Filters = []revel.Filter{
		revel.PanicFilter,             // Recover from panics and display an error page instead.
		revel.RouterFilter,            // Use the routing table to select the right Action
		revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
		revel.ParamsFilter,            // Parse parameters into Controller.Params.
		revel.SessionFilter,           // Restore and write the session cookie.
		revel.FlashFilter,             // Restore and write the flash cookie.
		revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
		revel.I18nFilter,              // Resolve the requested language
		MyFilter,
		revel.InterceptorFilter,       // Run interceptors around the action.
		revel.CompressFilter,          // Compress the result.
		revel.ActionInvoker,           // Invoke the action.
	}

Thats about it. Now we can access action and controller names in html template. Here is a sample of how my html template looks like

 <ul class="nav navbar-nav navbar-right">
                {{if eq .action "Register.Index"}}
                <li><a href="{{url "App.Index"}}">Login</a></li>
                {{else}}
                <li><a href="{{url "Register.Index"}}">Sign Up</a></li>
                {{end}}
 </ul>

Let me know, if you have any other way of handling such scenario or see any shortcoming in this.

~~ Whizdumb ~~
Email : sachin.xpert@gmail.com

One response

Comments are closed.