grails simple redirect not working - grails

Right, I appear to be doing this right and its so simple there really shouldn't be anything missing but for the life of me I can't see why its not working, I have a remote link on my list view like thus: -
<g:remoteLink action="makeReady" id="${testExecQueueInstance.id}">X</g:remoteLink>
The makeReady is empty at this point apart from I want it to show the line selected, so the controller only has this in it: -
def makeReady(Long myid){
redirect(action:"show", id:myid)
}
And the show action is the bog standard show that grails creates with just a Lond being passed in...
Why isn't this working? What dumbass obviousness thing have I missed that I'll be kicking myself over for the next few days?

<g:remoteLink makes ajax request, and your page is already rendered, server can't make redirect from it, it's already displayed.
There are two ways to make it working:
use standard link
respond with a JSON/Javascript, and make redirection on client side.
For second option it's going to be something like:
<div id="success"></div>
<g:remoteLink action="makeReady" id="${testExecQueueInstance.id}" update="success">X</g:remoteLink>
and
def makeReady(Long myid){
String url = createLink(action:"show", id:myid)
render(text: "window.location.href='${url.encodeAsURL()}'", contentType: "application/javascript")
}

Related

Return to previous page in ASP.Net Core MVC

From my client detail page I have a button to edit the client record which redirects to an edit page. I have a "return to client detail" link on the edit page which I want to redirect the user back to the previous client detail page.
<a asp-controller="Client" asp-action="Detail" asp-route-id="#Model.ClientID">Return to client detail</a>
Currently this works as expected but takes extra time as it reloads the detail page from scratch (ie running all the various db queries again). Since the user is really just cancelling the edit without any changes to the state of the client I am wanting to return the user to the previous detail page without having to go through the controller action again.
Essentially I am wanting to simulate the browser back button (to improve responsiveness) but i'm not sure how to implement this or whether it's good practice to do so. Some guidance would be appreciated.
Thanks
For IActionResult you can use this code:
public IActionResult Test()
{
return Redirect(Request.Headers["Referer"].ToString());
}
U know what? I hate JS so i will write answer with backend side. The HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. So simply read that and pass to view (always remember about XSS and validation, user can easly spoof HTTP request)
In action controller
if(Request.Headers["Referer"] != null)
{
ViewData["Reffer"] = Request.Headers["Referer"].ToString();
}
In view (razor)
#if(!string.IsNullOrWhiteSpace(ViewData["Reffer"]))
{
Return to client detail
}
You can use
<a href='javascript:history.go(-1)'>Return to client detail</a>
or onclick
Return to client detail
It should be like this
<input type="button" onclick= "history.go(-1)" value="Return to client detail" />
One note of caution using Request.Headers["Referer"] - if someone refreshes the destination page for some reason, Request.Headers["Referer"] will be empty.
Using history.go(-1) gives the expected behavior despite page refresh.
I think that you need to get rid of the idea of passing through the controller. If you need to browse quickliest with asp net core code about href you can try this.
<a asp-area="" onclick="history.go(-1);">Return to client detail</a>
I would never rely on my button, thinking a user will prefer it to browser back button.
I would say the correct way to solve this problem is to store the page state somewhere, for example, save ViewModel in TempData or Session. Then, if exists, load from it, instead of running db queries. It's quick and reliable.
This Request.Headers["Referer"] will not work if the user refresh the page or the page is been loaded twice, which mean, clicking back will not take you out of the current page.

Call a controller method in a view using onclick option

Hi I have the following problem. I would like to call a controller method which executes some sql statements by onklick option of a button or a link.
So I got a method "publish" in my controller. It looks sth like this:
def publish
do execute sql statements
flash[:notice] = 'sql statements executed.'
end
And in my view I would like to have a button or a link to call this method like this:
<input type="button" onclick="<% controller.publish %>">
But I get the error:
undefined local variable or method
I also tried to route it to use this method as :action. That did not work as well. I searched now for a while and found some solutions by making this method a helper_method, though I get the same error again.
I'm pretty new to Ruby and Rails so I hope you can help me.
If, in your view, you try something like <% controller.publish %>, that will call the publish action when the view is rendered, not when a user clicks on the button.
You can do something like this:
Create a route which will invoke publish when requested. For example, say the route is /publish.
In your view, put something like this:
<input type="button" onclick="window.location = '/publish'">
The value of the onclick attribute must be valid JavaScript, which will be executed when the button is clicked. In JS, setting window.location causes the browser to navigate to a different page. In this case, we are making the browser navigate to /publish, which will cause your publish action to be invoked. Whatever you render in publish will then appear in the browser.
In the code for publish which you show above, your Ruby syntax is wrong, but I am assuming that it is just a sample, not the actual code which you are using.
Your ruby on rails code is server side.
The code in your view e.g <input type="button" onclick="<% controller.publish %>">
is client side.
You can't call server side methods directly from client side code, since the client code is just running in the user's browser.
I've not used RoR so don't know the details but you will have to submit a message to the server from the client side code, at the server side you will then want to receive this and call the publish method from there.
Hope this helps.
First, if your SQL statements are going to change any data (which it looks like they are meant to), it's important that you use a POST request and not a GET request. To do that, you either need to use a basic form submission instead of clicking on a link, OR use javascript to submit the POST request when clicking on the link. Let's talk about the second way since that will stay consistent with how you want the app to look.
Assuming jQuery, you can use the jQuery.post method to post to your publish action when the button is clicked. In the success callback, you can display the message about the sql statements having been executed.
#alex-d's answer seems to be enough. Just use button_to and at the end of your publish action you can redirect to the same page (or the same action as before, if you're loading records to show in the view).
EDIT: From #alex-d's answer:
Create a route which will invoke publish when requested. For example, say the route is /publish.
GET '/publish' to: 'Controller#publish'
In your view, put something like this:
<input type="button" onclick="window.location = '/publish'">
Now on your controller method, redirect:
def publish
do execute sql statements
flash[:notice] = 'sql statements executed.'
redirect_to route_where_the_button_view_is_path #(or render if that controller method isnt necessary)
return #to avoid multiple render or redirect error (maybe not necessary)
end
PD: My code may not work at the first try, I'm working this out from memory.
GL & HF.

In a Rails app, how can I make a link load in a div as opposed to refreshing the whole page?

I'm still a beginner at web development. It's not my profession. So go easy.
I started building a rails app today, and realized it would make my application so much better if I could get certain links to display in a separate div instead of a new page, or refreshing the entire page. I'm not quite sure how to search for this, and I keep chasing red herrings with google.
Basically, I have a list in a div on the left side of the page, and when one item from that list is clicked, it should appear in the right div. (Nothing else on the page need be changed)
That's really as simple as it is. Do I need to use Javascript for this? Can I get away with the rails js defaults, or should I be using JQuery?
Is there a way to do this without javascript? I really just need a push in the right direction here, I'm tired of not even knowing how to search for this, or what documentation I should be reading.
Like I said, go easy, and you should just go ahead and err to the side of caution, and assume I know nothing. Seriously. :)
Thanks in advance,
-Kevin
(By the way, I'm developing with Rails 3)
Create your views (along with controllers) to be shown inside the div for each item on the left menu. Lets say we have the following structure now:
Item1 (Clicking on it will fetch:
http://myapp.com/item1)
Item2 (Clicking on it will fetch:
http://myapp.com/item2)
and so on...
make sure you only render the html to be put inside your content div. Should not include <head> <body> etc. tags
In your main page you may have your markup like this >
<div id="leftMenu">
Item 1
Item 2
</div>
<div id="content">
Please click on an item on the left menu to load content here
</div>
Finally, add the following Javascript (you'll need jQuery; trust me it's a good decision).
$("#leftMenu a").click(function () {
$("#content").load($(this).attr("href")); //load html from the url and put it in the #content element
return false; //prevent the default href action
});
You will need JavaScript if you want to avoid reloading the page. You can use link_to for links in your lists, and you'll need to use :remote => true to make it send AJAX requests to the server. The server will need to respond appropriately and supply HTML for your div.
link_to documentation is here: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to (and admittedly it isn't very useful for AJAX functionality).
The last post in this thread shows one possible solution you could use.

Accessing a list of params in controller

Im very new to grails (1.3.7) so please be patient :-)
I have a gsp where I have various checkboxes. A user can click on them and then send his answer to a controller. The controller is receiving this request correctly.
My problem is, that, for working with what the user chose, I have to check every parameter - to see if this checkbox was really checked. Thats really cumbersome and doesnt work very well, because the page displaying the checkboxes is dynamic - so the checkboxes which can be clicked are dynamic too. In my controller I dont know for which params I have to check then.
Is there any possibility to receive a list of all checkboxes (or better: all checked checkboxes) in my controller? I researched but didnt find an answer!
Thanks for answering! :-)
[EDIT]
Thank you,
params.name.each{i->
System.out.println(i);
}
is very simple and works :-) It just gives back the checked ones
It must be passed as an extra request parameter (it's a limitation of http). You can add following field into your form, for example:
<input type="hidden" name="checkboxes" value="${myCheckboxesNames.join(',')}"/>
or making same using JavaScript, as it names are dynamic on client side.
BTW, you can also check all request parameters, by
params.each { name, value ->
// so something
}
so if you are using some special prefix/suffix for this checkbox names, it would be:
params.entrySet().findAll {
it.key.startsWith(prefix)
}.each {
println "Checkbox $it.key = $it.value"
}

Adding a "previous" link

What the appropriate way to do this?
ViewData["PreviousPage"]=Request.UrlReferrer.PathAndQuery;
this doesnt work if directly accessing.
EDIT: I did a null check on Request.UrlReferrer, seems to be fine (?)
If directly, it's impossible this way. URL referer is set only when clicking a link.
If you're interested only in "Previous Page" link working inside your website, then you can store current URL in session, and retrieve it during next request, then replace with a new current url. Ugly, but working.
Is there some reason this needs to be server-side instead of client-side? If you can deal with client side, Javascript is the answer:
<input type=button value="Back" onClick="history.go(-1)">
This uses the browser's built-in back functionality -- it essentially mimics clicking the "Back" button.
Put this somewhere in your Base Controller or Custom Filter:
TempData["PreviousPage"] = TempData["CurrentPage"];
TempData["CurrentPage"] = Request.Url;

Resources