I have one gsp file which calls a method like this:
<g:link id="${child.id}" action="callChildProfile" controller="profile">${child.firstname}</g:link>
which calls this method
def callChildProfile(Long id){
childInstance = Child.get(id)
System.out.println(childInstance.firstname + " child instance")
redirect(action: "index")
}
this method set a child instance to a public variable called child instance but when the redirect happens the variable is reset.
The reason I redirect is because I want to load up the index page from this controller.
Index looks like this:
def index() {
def messages = currentUserTimeline()
[profileMessages: messages]
System.out.println(childInstance + " child here")
[childInstance : childInstance]
}
By default controllers are prototype scoped, which means the instance of ProfileController used will be different between the request which calls callChildProfile and the request which calls index. Thus, the object level childInstance variable won't be available between requests.
To use the Child instance in the index call, look at the chain method:
callChildProfile(Long id){
// do usual stuff
chain(action:"index", model:[childInstance:childInstance])
}
def index() {
// do other stuff
[otherModelVar:"Some string"]
}
When returning a Map from index the model of the chain call will be automatically added, so your childInstance from the callChildProfile will be available for the gsp.
Variables in controller methods (actions) have a local scope, thus, only can be used in that method. You should pass the id from new instance and use that id for retrieve the object.
redirect action: "index", id: childInstance.id
and index could be
def index(Long id){
childInstance = Child.get(id)
Then you can conclude that you don't need the callChildProfile method
or you can use params
def index(){
childInstance = Child.get(params.id)
if(childInstance){
doSomething()
}
else{
createOrGetOrDoSomethingElse()
}
}
Related
I am new to grails and I am trying to override the redirect method in groovy controller. I refereed this Override Grails redirect method. But I do not understand how do I access and pass the http request params to the redirect override in BootStrap.groovy.
redirect(action: "logout", params: [lang: params.lang])
If you implement a wrapper via metaClass on a controller (just like mentioned in your linked question), you can simply access the "active" controller object via "delegate" in your implementation closure:
def ctx = servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
def app = ctx.getBean("grailsApplication")
app.controllerClasses.each() { controllerClass ->
def oldRedirect = controllerClass.metaClass.pickMethod("redirect", [Map] as Class[])
controllerClass.metaClass.redirect = { Map args ->
// delegate is the instance of <controllerClass> where "redirect" just gets executed.
// the current http request can be accessed via a getter on controller classes
println delegate.getRequest()
oldRedirect.invoke delegate, args
}
}
alternatively, you could use the RequestContextHolder to obtain the current requestAttributes and extract the request from there (see org.codehaus.groovy.grails.plugins.web.api.CommonWebApi.java in Grails 2 or grails.web.api.ServletAttributes.groovy in Grails 3)
Note: Second action only allows POST method. we can not hit that action by the user.
static allowedMethods = [save: "POST",booked:"POST"]
def save()
{
// did save operation here
redirect action:'booked'
}
def booked()
{
//did the operation related with this
render view :'payment'
}
Try forward
def save()
{// did save operation here
forward action:'booked'
}
def booked()
{
//did the operation related with this
render view :'payment'
}
All the parameters passed to save will directly get passed to booked method. Is this what you need?
You may do this as below by directly calling the method within save method
def save(){
booked()
}
I have a controller method that needs to invoke (and get the HTML result from ) some other arbitrary "child" controller action. The route for the "child" action is encoded in a URL. What I want to do is parse the URL intro a route, get a controller that can execute the child action, simulate a request to the child action (obviously with some reasonable context), and then get the resulting HTML back.
I have tried a range of things (including an hour of trolling through SO posts on route parsing, creating controllers, etc.) but I'm stumped.
For example, ...
class SomeController
{
public ActionResult Outer()
{
string exampleInnerPath = "/Other/Child/20";
string output = EvaluateChildPath(exampleInnerPath);
return Content(output, "text/xml");
}
}
class OtherController
{
public PartialViewResult Child(int arg)
{
return PartialView(arg);
}
}
How would you write EvaluateChildPath()?
Any direction would be appreciated!
I have the controllers:
Controller A
{
public ActionResult ExecuteSomeStuff()
{
....use TempData
returns a View("StuffMade", SomeModel);
}
}
and
Controller B
{
public ActionResult DoStuff()
{
...fill up TempData
returns RedirectToAction("ExecuteSomeStuff", "A");
}
}
The problem is that the ExecuteSomeStuff method on controller A is executed twice.
I dont need the actual redirect to be made, I just want the result(the view) from the ExecuteSomeStuff method to be returned for DoStuff method.
I dont want to have a reference to controller A in controller B in order to call the method directly.
Is there any way to do this without the physical redirect or new reference to be made to controller A in controller B??
If I'm understanding you correctly, instead of a RedirectToAction, you can return the ExecuteSomeStuff View from Controller B. You will need to be able to set the Model to pass into the View from Controller B. So you may still need to make some reference to the methods used in Controller A.
Controller B:
{
public ActionResult DoStuff()
{
...fill up TempData
//set the model then Return the View with the Model passed in
return View("ExecuteSomeStuff","A",SomeModel);
}
UPDATE
This will look for a View with the same name as the action ExecuteSomeStuff without actually entering the ExecuteSomeStuff action. If your View has a different name, you can explicity specify the View to return like this:
return View("../A/theCorrectView.aspx", model);
Is it possible to access the current controller instance from within a TagLib? For example:
class FooTagLib {
static namespace = 'foo'
def msg = { attrs, body ->
// Can I get a reference to the current controller here?
}
}
I want to do this because I store some data in a property of the controller and want to access it within the TagLib. I realise this may sound strange, but just humour me....
Inside your msg tagLib:
grailsApplication.getArtefactByLogicalPropertyName('Controller', pageScope.controllerName)
Like Views, you have access to the current controller and action through controllerName and actionName
Try something like this...
def ctl = grailsApplication.getArtefactByLogicalPropertyName('Controller', 'whateverController')