Specify a bean to bind data to - grails

Working in grails allows you to be quite DRY, but I still find myself frequently doing this:
def bookInstance = new Book(params)
if (!bookInstance.validate()) {
render(view: "create", model: [bookInstance: bookInstance])
}
else {
// stuff...
}
Is there a way to specify that a particular controller/action should bind a particular domain and then all the validation and view re-rendering happens before my action is executed? That way I only need to worry about //stuff....

You may use the Interceptors for validation, but interceptors cant render view.

Related

Error handling using controller in grails

I have an error.gsp file that handles errors. I want to add server logic to the errors behaviour so I changed my mappings
from: "500"(view: '/error')
to: "500"(controller: 'errors')
in my UrlMappings class.
And added a new controller:
class ErrorsController {
def index() {
println(request.exception)
render view: '/error'
}
}
I need the exception data and it is NULL, yet it exists in the view.
The model is also null.
How can I get the exception object in the errors controller?
Regards, Ido

how to pass one parameter value from admin controller to reports controller in grails

i want to pass caterer value from admin controller to reports controller
getreports.gsp
<g:form url="[admin:catererInstance, action:'save']" >
<div value="${adminInstance.caterer}"></div>
</g:form>
reportscontrooler.groovy
class ReportsController {
def index() {
redirect(action: "_getreports", params: params)
}
def _getreports(){
def adminInstance=new Admin(params)
def adminList=Admin.list().caterer
render(template:"getreports",model:[adminInstance:adminInstance])
}
}
I have modified your code and simply explain how to pass value to controller from your getreports.gsp
getreports.gsp
<g:form url="[admin:catererInstance, action:'save']" >
// Click SEND Button to send value to getreports action
<g:link class="btn btn-info btn-sm" action="getreports" resource="${adminInstance}">SEND</g:link>
</g:form>
reportscontrooler.groovy
// import your admin class here.
class ReportsController {
def index() {
redirect(action: "_getreports", params: params)
}
def _getreports(Admin adminInstance){
// You can get your values Here.
println "adminInstance: "+adminInstance
}
}
You say you have two controllers, but your code shows both of your methods in ReportsController only. If that is the case, you should use forward instead of redirect. If you really meant to issue a redirect to AdminController from ReportsController, then you need to supply controller parameter in your redirect.
Although, this should do the trick, I highly suggest you not to use a redirect here. Better create a new service, maybe ReportsService and move your _getReports() method there. Ideally, services should be handling all your business logic, not controllers.

Grails - URL mapping/default action and flow

Question -
I've noticed that some applications I test with have calls to another view/controller from an action submit, but when that page is rendered, instead of seeing:
$controller/$page
I see:
$controller/index
Is this an issue with the URL mapping configuration? Default action? Just curious, because it just appears to be the URI mapping to a default instead of the actual action.
view code:
<table>
..
<g:actionSubmit class="stats" action="stats" value="View Stats"/>
..
</table
controller:
def stats() {
def teamId = Team.get(params.id)
def allPlayers = Player.withCriteria {
eq('team', teamId)
and {
eq('isActive', true)
}
}
[allPlayers:allPlayers, teamId:params.id]
}
UrlMapping:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
}
Edit
I actually figured out what it is. Which makes me even more confused.
The grails actionSubmit has an action tied to it. That form was just a normal form, without call:
<g:form>
<g:actionSubmit class="stats" action="stats" value="View Stats"/>
<g:actionSubmit class="schedule" action="schedule" value="View Schedule"/>
<g:form>
So by default, the form redirects the action to $controller/index. If you add an action call in the g:form tag, those two buttons will direct to the correct page, but the URI will now be $controller/$g:form_action.
I guess I don't get the point of the actionSubmit's action if the g:form is needed as a wrapper.
Yes, index is the default action for all controllers. So if you do not specify one, that is the page you will land on for the controller.
It is discussed in further detail on their website. Namely, the rules are:
If only one action is present the default URI for a controller maps to
that action.
If you define an index action which is the action that
handles requests when no action is specified in the URI /book
Alternatively you can set it explicitly with the defaultAction property:
static defaultAction = "list"

Grails pattern to reuse template on error

I have a gsp template, where the data for create view is passed through the controller.
def create = {
def bookInstance = new Book()
bookInstance .properties = params
def map = getDefaultValues()
render(template: "create", model: [bookInstance : bookInstance ,
title: map.title,
somelist: somelist
....])
the gsp template
<g:select optionKey="id" from="${somelist}" name="somelist.id" value="${bookInstance ?.somelist?.id}" noSelection="['null': '']"></g:select>
now, in the save method, if there is an error, it returns currently populated and validated instance (default scaffold implementation)
render(template: "create", model: [bookInstance : bookInstance ])
But the fields in the gsp (error page rendered from save action) is empty. I could see the reason as it looks the value in "${somelist}" , but it is not used in save method. Do i just need to check for null in the gsp and use whichever map is available, or any better method (passing all the map in the save method is not an option) ..
thanks in advance..
I figured it out.. I have to pass the same map as was in the create closure .. the reason why we were passing the maps in create is because we wanted to override the default list.. the populated values in bookInstance is only used to preserve the user selection, but not all the values..

'New' and 'Create' RESTful action names or 'Create' for both in ASP.MVC

The rails convention is to use New and Create for RESTful action names. The .NET MVC convention appears to be to use Create for both (usually with a post restrictor on the action intended to the true 'Create' method).
Personally I would prefer to use New and Create in .net but have been using Create for both given the convention. What (if any) is the benefit of the .NET MVC convention of using Create for both actions?
The same goes for Edit and Update?
One benefit is that you can write code like:
<% using (Html.BeginForm()) { %>
... instead of code like:
<% using (Html.BeginForm(new RouteValueDictionary{ "action", "Update" })) { %>
Similarly for error handling:
if (!ModelState.IsValid)
{
return View(model);
}
... instead of:
if (!ModelState.IsValid)
{
return View("Edit", model);
}
MVC's convention is that related stuff is named the same, not that your actions must have certain names.

Resources