开发者

How to upgrade the :update=>'div_id' option of remote_form_for from Rails 2 to Rails 3?

I can't figure out how to upgrade this code from Rails 2 to Rails 3:

<% remote_form_for(item, :update => 'div_id') do |f| %>
... 

I tried this:

<%= form_for :item, :remote => true, :url => { :controller => "items", :action => "create" }, :update => 'div_id' do |f| %>
...

It creates the开发者_开发百科 new item but it fails in updating the content within <div id="div_id"></div> tags. It seems Rails 3 no longer supports the ":update" option for a remote form_for. Any suggestion?


You could use RJS, but that's being deprecated too (and for good reason). The simplified, best-practices way to handle this in Rails 3+ is as follows (assuming jQuery):

# your_view.html.erb
<div id="receiver-id"></div>

<%= form_for :some_model, :remote => true, :id => 'form-id' do |f| %>
  ...
<% end %>


# application.js (or any other .js loaded on the page)
$(function(){
  $('#form-id').bind('ajax:success', function(xhr, data, status){
    $('#receiver-id').html(data);
  });
});

The ajax:success hook gets called by the jquery-ujs (aka jquery-rails, aka rails-ujs) remote link/form handler. See for yourself. There are lots of other callbacks/hooks available for you to use, too. If you wanted to make this even more flexible, you could use live instead of bind, and bind to a class that dictates where the ouput goes (e.g. "sidebar") and then all remote links/forms with the sidebar class would have their HTML response go to div#sidebar.


The most straightforward way to do this would be to write a javascript view template, e.g. create.js.erb which would look something like this:

$('#div_id').html("<%= escape_javascript(render(@item)) %>");

(depending on your setup, of course, I'm assuming an @item variable and an associated _item partial)

Edit:
coreyward is right. This is the RJS way which is more of the old fashioned Rails 2.x "Rails way". It's probably more familiar, but has issues. Your specific case is one of them, actually, as typically you might bind to an HTML element to update using the record's id (e.g. div #item_1), and in the create case there is no id available beforehand, complicating matters.

Binding via clientside JS eliminates this issue. RJS works in something of a vacuum, making assumptions about the state of the client's HTML and having no access to it.


I know the question is old but I when migrating to Rails 3 I found a pretty good way of doing this, so I thought I would post it here in case anyone else is in a similar solution.

In layouts/update_page.js.erb I put this file:

$j('#<%=@update_div_id||"list_div"%>').html('<%= escape_javascript render(:partial => (@partial_div||"index"), :locals => @local_hash) %>');

This is mainly used for searches that use remote, so in the index action in the controller, I just added the following code.

respond_to do |format|
  format.html
  format.js {render 'layouts/update_page'}
end

Since remote is being used, it will always try to use javascript first, so it will render the update_page.js.erb file from above. For us, we almost always use the div#list_div on our index pages, so we update that by the default, however if you need to update something different, you can pass in @update_div_id, and if you need to render a different page, you can pass in @partial_div.

To clarify, for a lot of things, it is probably better practice to use the callbacks, but I found this to be a much easier way, when we had to migrate over nearly 100 of these calls.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜