What is considered the Rails Way for Ajax Forms
Until today I thought the way I use Rails forms + jQuery UJS was the right way to do it, but the upgrade to jQuery 1.7 'broked' the way I did it so far.
How to do this?
I want to use Ajax with my forms. The ajax response should either render the form again (e.g. when errors occur) or redirect to a success page. (It should maybe do more, like showing modals, but I want to keep this example simple).
1. Using EJS and $('#formid').html(...)
That is what I did until to date. My ajax response was an ejs template which returned javascript code to render the form again (with errors) or depending if it was an error redirected the user to success page:
<% unless @success_submit %>
$('#form_wrapper').html('<%= escape_javacsript( render :partial => 'form' ) %>');
<% else %>
document.location = '/success_thank_you';
<% endif %>
Now imagine the form contains an error message div like
<div class="error_message">BlaBla</div>
To add a nice effect I had a general jQuery.live event bound on ajax complete which highlighted errors.
$('form').live('ajax:complete', function() {
// do stuff like highlighting all error messages in that form
});
That doesn't work with jQuery1.7 + jquery-ujs anymore (probably by good reasons). So I guess the way I did it was not right.
2. Using above way but repeat myself
Instead of binding the ajax:complete event I could do the "error highlighting stuff" in the EJS like
$('#form_wrapper').html('<%= escape_javascript( render :partial => 'form' ) %>');
$('#form_wrapper form .error_message').fadeIn();
But that would mean I would have to repeat the second line in almost each EJS which renders forms. And of course I want to keep it DRY.
3. Ajax response renders pure html, ajax:complete event handles display
A complete different solution would be that the ajax response simply would render pure html and my custom ajax:complete handler would take care of displaying the form. The handler would look like
$('form').live('ajax:success', function(ev, data, status, xhr) {
$(this).html(data);
// and e.g. highlight stuff
$(this).children('.error_message').fadeIn();
});
That would work. But now what should I do if my server decides not to render the form again (e.g. after successful signup) but instead redirect to another url or showing a modal form. The server could respond with something like that
<script>
document.location = '/success.blabla/';
</script>
But is that a good solution ?
4. Custom JSON protocol
Probably a good solution would be to use version 3 but instead of simply replacing the current form with the returned html we could create some custom json protocol. That way we could even let the server respond with stuff like
- first show modal ( like 'Signup Success')
- redirect to login page
The ajax:success handler could check if the response is pure html, in that case it would replace the current form with the html code. But if the response is a JSON array it would handle that, e.g. server responds with
{ html: '<%= render :partial => 'something' %>',
show_modal: '<%= render :partial => 'modal_template' %>',
redirect_after_modal: '/login_page'
}
The ajax:success handler would have handle it like
$('form').live('ajax:success', function(ev, data, status, xhr) {
// try parsing json
if (data.json['show_modal') { // show modal code.... };
if (data.json['redirect']) { document.location=data.json['redirect']);...
});
How are you doing this stuff
Obviously there are many ways how you handle ajax forms. But how are you doing it, and what is considered best practice with Rails ?