Wednesday, July 25, 2007

usage of form_remote_tag and remote_form_for


<%= form_remote_tag :html => { :action => url_for(:controller => "some", :action => "place", :id => 1), :id => "form_id" }, :update => "ajax_update_div" %></form>

A "fall-through" target for browsers that doesn‘t do JavaScript can be specified with the :action/:method options on :html.
<% form_remote_tag({:html => { :action => url_for(:controller => "other", :action => "place", :id => 1), :id => "form_id", :method => :get }, :url => url_for(:controller => "some", :action => "place", :id => 1), :update => "ajax_update_div"}) do%>
<% end %>

<% remote_form_for :person, @person, :html => {:id => 'form_id', :name => 'form_name', :method => :get, :action => url_for(:controller => 'where', :action => 'some', :id => @person)}, :url => { :action => "test" }, :update => 'ajax_div' do |f| %>
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
Biography : <%= f.text_area :biography %>
Admin? : <%= f.check_box :admin %>
<% end %>


form_for(object_name, *args, &proc)
Creates a form and a scope around a specific model object, which is then used as a base for questioning about values for the fields. Examples:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
Biography : <%= f.text_area :biography %>
Admin? : <%= f.check_box :admin %>
<% end %>

Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that’s <% %>, not <%= %>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates the API for the stand-alone FormHelper methods, but without the object name. So instead of text_field :person, :name, you get away with f.text_field :name.
That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance variable convention, so while the stand-alone approach would require text_field :person, :name, :object => person to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with :person, person and all subsequent field calls save :person and :object => person.
Also note that form_for doesn’t create an exclusive scope. It’s still possible to use both the stand-alone FormHelper methods and methods from FormTagHelper. Example:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
Biography : <%= text_area :person, :biography %>
Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. Like collection_select and datetime_select.
Html attributes for the form tag can be given as :html => {…}. Example:

<% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>
...
<% end %>

You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder like so:

<% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= text_area :person, :biography %>
<%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

In many cases you will want to wrap the above in another helper, such as:

def labelled_form_for(name, object, options, &proc)
form_for(name, object, options.merge(:builder => LabellingFormBuiler), &proc)
end

No comments :