开发者

Ajax Callbacks in Rails 3 with Prototype, not jQuery

开发者 https://www.devze.com 2023-02-18 07:01 出处:网络
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.

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 of Ajax.Request. Do NOT use :remote => true, since this will attempt to use Ajax.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);
});
0

精彩评论

暂无评论...
验证码 换一张
取 消