Hot to implement grails server-side-triggered dialog, or how to break out of update region after AJAX call - ajax

In grails, I use the mechanism below in order to implement what I'd call a conditional server-side-triggered dialog: When a form is submitted, data must first be processed by a controller. Based on the outcome, there must either be a) a modal Yes/No confirmation in front of the "old" screen or b) a redirect to a new controller/view replacing the "old" screen (no confirmation required).
So here's my current approach:
In the originating view, I have a <g:formRemote name="requestForm" url="[controller:'test', action:'testRequest']", update:"dummyRegion"> and a
<span id="dummyRegion"> which is hidden by CSS
When submitting the form, the test controller checks if a confirmation is necessary and if so, renders a template with a yui-based dialog including Yes No buttons in front of the old screen (which works fine because the dialog "comes from" the dummyRegion, not overwriting the page). When Yes is pressed, the right other controller & action is called and the old screen is replaced, if No is pressed, the dialog is cancelled and the "old" screen is shown again without the dialog. Works well until here.
When submitting the form and test controller sees that NO confirmation is necessary, I would usually directly redirect to the right other controller & action. But the problem is that the corresponding view of that controller does not appear because it is rendered in the invisble dummyRegion as well. So I currently use a GSP template including a javascript redirect which I render instead. However a javascript redirect is often not allowed by the browser and I think it's not a clean solution.
So (finally ;-) my question is: How do I get a controller redirect to cause the corresponding view to "break out" of my AJAX dummyRegion, replacing the whole screen again?
Or: Do you have a better approach for what I have in mind? But please note that I cannot check on the client side whether the confirmation is necessary, there needs to be a server call! Also I'd like to avoid that the whole page has to be refreshed just for the confirmation dialog to pop up (which would also be possible without AJAX).
Thanks for any hints!

I know, it's not an "integrated" solution, but have you considered to do this "manually" with some JS library of your choice (my personal choice would be jQuery, but any other of the established libraries should do the trick)? This way you wouldn't depend on any update "region", but could do whatever you want (such as updating any DOM element) in the response handler of the AJAX request.
Just a thought. My personal experience is that the "built-in" AJAX/JS stuff in Grails often lacks some flexibility and I've always been better off just doing everything in plain jQuery.

This sounds like a good use-case for using web flows. If you want to show Form A, do some kind of check, and then either move onto NextScreen or show a Dialog that later redirects to NextScreen, then you could accomplish this with a flow:
def shoppingCartFlow = {
showFormA {
on("submit") {
if(needToShowDialog())return
}.to "showNextScreen"
on("return").to "showDialog"
}
showDialog {
on("submit").to "showNextScreen"
}
showNextScreen {
redirect(controller:"nextController", action:"nextAction")
}
}
Then you create a showDialog.gsp that pops up the dialog.
--EDIT--
But, you want an Ajax response to the first form submit, which WebFlow does not support. This tutorial, though, will teach you how to Ajaxify your web flow.

Related

Ember JS best way to show a full screen loading screen button press

I'm new with Ember and I would like to show a full screen overlay when a user presses a "get stuff from the server" button.
What is the best way to achieve this?
Does Ember already provide something built-in? Or is it that the only way is to have a piece of HTML in one of my templates, to show/hide it when the promise where I make the AJAX call returns?
You have a few options available to you.
The first concerns a route change. Conventionally speaking, if the user is hitting a button that transitions to another route, a separate route can be created to handle this in-between loading experience.
To describe this briefly, if you have a route named foo, creating a sibling route named foo-loading with an associated template, will show a "foo-loading" page state while things are being fetched, and then dismiss it once things are good.
Alternatively, as you've hinted, if the call to action for a user intends an updated result on the same route, a loading service could be useful. In your application template, you could have a loading div that is hidden by default. Prior to initiating an AJAX request, you could turn the loading state on and reveal the loading div. Then, once the AJAX call is settled, the finally block could include a call to conceal the loading div.
This latter approach would involve a conditionally loaded block in the primary application template, a loading service handling show and hide, and a loading template.
You could use ember-modal-dialog to create a loading screen component that gets rendered when you're waiting for your ajax request.
For example:
// view.js
showLoadingScreen: true
// view.html
{{#if showLoadingScreen}}
{{loading-screen}}
{{/if}}
// loading-screen.html
{{#ember-modal-dialog}}
<div class="loader-full-screen-class"></div>
{{/modal-dialog}}
The advantage of the component/ember-modal-dialog is that this pattern is usually implemented as a modal, and this library is the standard in ember. The component then allows you to put it anywhere you need it to be.

Problem showing a messaje to the user using ASP MVC TempData

I'm using TempData to show a message to the user. I put a string in the TempData and later I read the string, and if it is not empty, then I show a DIV that contain the message.
All works fine, and if the user refresh the page the message are not shown (Thats what I want). The problem is that if the user navigate to other page and then press the back button in the browser, then the message are shown again, and I do not want this.
What could I do to avoid this behaviour?
Thanks.
This is the code I use to read the TempData (Razor + VB). There is a DIV #commonMessage, with this code I put the string inside the div and show it. As I said before, it's working, but the only problem is that the TempData is still there if the user click back in the browser.
#If Not IsNothing(TempData("MessageUser")) AndAlso TempData("MessageUser") <> String.Empty Then
Dim str As String = TempData("MessageUser")
#<script type="text/javascript">
$(document).ready(function () {
$('#commonMessage').html("#str");
$('#commonMessage').delay(400).slideDown(400).delay(4000).slideUp(400);
})
</script>
End If
EDIT: Seems like the TempData are being catched, because if I Disable the cache for the action where I'm showing the message (Using the Attribute System.Web.Mvc.OutputCache(NoStore:=True, Duration:=0, VaryByParam:="*")) the problem dissapears. But It would be better I we could find a method that not involve disabling the cache...
REQUESTED EDIT: I'm very newby in ASP, so I try to clarify what i'm triying to do. When an user performs an action (edit a client, for example), I redirect the client to the client list page, and I show a message that tell to the user "The client data was update susessfully". I'm triying to do it in a way that makes the message to be show only once. Maybe the TempData is not the right way (I don't know, 'cos i'm learning yet), but the target is to show a message to an user only once (no matter if the urser refresh or if the user go to other page and then press back in the browser)... using TempData or using something more adequate to our purpose.
Essentially, you are wanting TempData to do what you want, rather than using the right tool for what you want.
TempData is, by design, intended to be used for caching data across HTTP redirections. That is what it exists for. It is not clear from your post if this is the scenario that you are using.
Ie:
Page redirection, with data in TempData, that is then displayed to the user. Refresh the page you have arrived on, and the TempData is no longer there (there has been no redirection, just a refresh).
If the user then navigates to another page, then uses the back button, the browser will have cached the html of your page and will redisplay that. That is the correct behaviour.
I also think that in your testing, you are getting it wrong. Ie, by disabling the caching, you are just knocking out TempData altogether and you will not get the correct behaviour. Ie, the message will NEVER appear, not just when you hit the back button.
Your jQuery looks inefficient. You are making it do things it doesn't need to do. You could use razor to populate your div with your message. Set the div to not display, ie:
<div id="commonMessage" style="display:none;">
Then use jQuery to show it:
$('#commonMessage').show();
Your post isn't that clear, but in summary, I would say you are seeing what you should.
Maybe you should describe, in an Edit, what you want your app to do. That way it would be easier to answer. As things stand, you have told us what happens and what you put in your view, but it is not clear what you expect.
You should also understand TempData better: it only persists between Controller actions, ie, when a redirect occurs. It stores its data in the Session store, which I believe is affected by the caching attribute you mention.

CodeIgniter jQueryUI dialog form example

I am trying to use CodeIgniter and jQuery-ui dialog to create a modal window with form to update user information.
The process should be like:
1. Press a button on a view page.
2. A modal window pops up.
3. Inside the window is a form that a user can fill.
4. If the user filled something before, the information should be shown in corresponding field
5. Click the update button on the modal window to save the changes to database.
Can anyone provide a good sample of this process?
I used ajax to pass the data but it didn't work when I was trying to update the data to the database. It would be nice if an example of how to pass data from ajax to php and how php handle that.
Thanks,
Milo
well the jquery bit for post(), get(), ajax() works the same in any measure you would normally use it.. key difference here is with CI you can't post directly to a file-name file-location due to how it handles the URI requests. That said your post URL would be the similar to how you would access a view file normally otherwise
ie: /viewName/functionName (how you've done it with controllers to view all along. post, get, ajax doesnt have to end in a extension. I wish I had a better example then this but I can't seem to find one at the moment..
url = '/home/specialFunction';
jQuery.get(url, function(data) {
jQuery("#div2display").html(data);
});
in the case of the above you notice despite it not being a great example that. you have the url with 2 parameters home and specialFunction
home in this case is the controller file for home in the control folder for the home file in views the specialFunction is a "public function" within the class that makes the home controller file. similar to that of index() but a separate function all together. Best way I have found to handle it is through .post() and a callback output expected in JSON cause you can form an array of data on the php side json_encode it and echo out that json_encode and then work with that like you would any JSON output. or if your just expecting a sinlge output and not multiples echoing it out is fine but enough of the end run output thats for you to decide with what your comfortable doing currently. Hopefully all around though this gives you some clairity and hopefully it works out for you.

How to prevent ajax driven form from being submitted twice?

I am taking my first steps with Ajax while working on a Grails application. I am using
<g:form ...>
<g:submitToRemote ... />
</g:form>
in the most simple way and it worked great out of the box (Thanks grails!). The problem is, that the Ajax call needs about 2 seconds to return and update the html (at least on the test system) and during that time, the user can (and actually does quite often) hit the submit button again. At the moment this results in a 2nd call being made that finally ruins the output (an error msg says, that one cannot submit the same data twice).
What is the best way to prevent this?
Thanks in advance for your input!
The best way to handle this is to disable the submit button in your onSubmit() function. Honestly, I don't know why more sites don't do this. I often go the next step and instead of disabling the submit button, I put the submit button in a span tag and replace the contents of the span tag with static text "Please wait..." That way your users get visual feedback they pressed the button and "top men are working on it".
As dj_segfault said you can do that.
If you want to validate this in your controller, take a look in "Handling Duplicate Form Submissions" in the official docs:
http://grails.org/doc/latest/guide/theWebLayer.html#formtokens

jQuery Showing an Ajax loader during transmission & Prevent Multiple Submits

I have an app that has several different types of form elements which all post data to the server with jQuery AJAX.
What I want to do is:
Show a loader during AJAX transmission
Prevent the user from submitting twice+ (clicking a lot)
This is easy to do on a one off basis for every type of form on the site (comments, file upload, etc). But I'm curious to learn if that is a more global way to handle this?
Something that's smart enough to say:
If a form is submitting to the server and waiting for a response, ignore all submits
Show a DISABLED class on the submitted / clicked item
Show a loading class on the class="spinner" which is closest to the submit item clicked
What do you think? Good idea? Done before?
Take a look at the jQuery Global Ajax Event Handlers.
In a nutshell, you can set events which occur on each and every AJAX request, hence the name Global Event Handlers. There are a few different events, I'll use ajaxStart() and ajaxComplete() in my code sample below.
The idea is that we show the loading, disable the form & button on the ajaxStart() event, then reenable the form and hide the loading element inside the ajaxComplete() event.
var $form = $("form");
$form.ajaxStart(function() {
// show loading
$("#loading", this).show();
// Add class of disabled to form element
$(this).addClass("disabled");
// Disable button
$("input[type=submit]", this).attr("disabled", true);
});
And the AJAX complete event
$form.ajaxComplete(function() {
// hide loading
$("#loading", this).hide();
// Remove disabled class
$(this).removeClass("disabled");
// Re-enable button
$("input[type=submit]", this).removeAttr("disabled");
});
You might need to attach to the ajaxError event as well in case an AJAX call fails since you might need to clean up some of the elements. Test it out and see what happens on a failed AJAX request.
P.S. If you're calling $.ajax or similar ($.getJSON), you can still set these events via $.ajaxStart and $.ajaxComplete since the AJAX isn't attached to any element. You'll need to rearrange the code a little though since you won't have access to $(this).
I believe you have to do 2 for sure and 3 to improve usability of your app. It is better to keep backend dumb but if you have a security issue you should handle that too.

Resources