Ajax Callbacks in Rails 3 with Prototype, not jQuery
I'm upgrading an app from Rails 2 to 3 and am reworking all of the remote functions to use Unobtrusive Javascript. Where I'm struggling is handling ajax callbacks in UJS.
There are a lot of resources I've found that sh开发者_开发知识库ow how to implement these callbacks with jQuery, but not much for prototype. Perhaps you can help me figure this out.
In Rails 2, I had this:
<% remote_form_for @foo, {:loading => "loading_function()", :complete => "complete_function()" } do |f| %>
...
<% end %>
In Rails 3, I have this:
<%= form_for @foo, :remote => true do |f| %>
....
<% end %>
From what I've figured out so far (which may be wrong), I need to attach my old loading/complete functions to the form so that they'll be fired by the handleRemote function in Rails.js. I'm just not sure how to go about that.
Again, I'm doing this in Prototype. So answers specific to that framework are appreciated.
The answer is the following:
<%= form_for @foo, :remote => true do |f| %>
...
<% end %>
...
<script type='text/javascript'>
$('edit_foo').observe('ajax:before', loading_function());
$('edit_foo').observe('ajax:complete complete_function());
</script>
Try this link. Yes, it is JQuery, but JQuery and Prototype do not differ the way how things work together. Here is a code fragment that adds a new task directly in the index page - and it uses Prototype:
views/tasks/_newform.html.erb:
<%= form_for(@task, :remote => true) do |f| %>
<div>
<%= f.label 'Add a new task: ' %>
<%= f.text_field :name %>
</div>
<div>
<%= f.submit %>
</div>
<% end %>
views/tasks/index.html.erb:
<div id='newform'>
<%= render :partial => "newform", :locals => { :@task => Task.new } %>
</div>
views/tasks/create.js.rjs:
page.insert_html :after, 'tablehead', :partial => @task
page.replace_html 'newform',:partial => "newform", :locals => { :@task => Task.new }
Edit: you need to add "format.js" to our create method of the task controller
For people with a similar issue, it may also help to look at the source code for the remote helpers in the Rails 2.3.x source code.
In my case, I wanted to figure out what to do with the ':update' parameter, as in:
remote_form_for(@obj, :update => "new_obj", :before => "some js code") do |f|
I had to find the update functionality in the remote_function code.
For my specific issue, it looks like it's impossible to get the equivalent of :update
with Rails 3 UJS helpers. The rails.js
in Rails 3 wraps :remote => true
requests with the Ajax.Request(...)
, whereas the :update
function in Rails 2 wraps Ajax requests with Ajax.Updater(...)
. For people looking to replace the :update
feature from Rails 2, I see 2 options:
Switch to jquery-rails, so that you can access the response from the Ajax request, with code like this:
$("#elem").bind("ajax:complete", function(et, e){ $("#results").html(e.responseText); });
Write your own Prototype based code to grab the form and submit it via ajax, using
Ajax.Updater(...)
instead ofAjax.Request
. Do NOT use:remote => true
, since this will attempt to useAjax.Request
.
Side note: I played around with the callback object provided in the ajax:complete
event
$('new_obj').observe('ajax:complete', function(request){
console.info(request);
});
The request
object doesn't appear to contain the response anywhere in it. It is pretty massive, though, so I could be wrong. Hopefully this will help someone else trying to upgrade from Rails 2 to 3, though.
There's a way to get the response from the Ajax.Request invocation, if you were using remote_form_for with :update option. So, you probably don't need to change it to use Ajax.Updater as a workaround. Basically, you use respone.memo.responseText, in your example it would be something like this:
$('new_obj').observe('ajax:complete', function(response){
console.info(response.memo.responseText);
// Probably you would use it like this:
$('new_obj').update(response.memo.responseText);
});
精彩评论