Topic: Automatic submit on collection_select change

Hi,

I'm getting into AJAX at the moment, and have a question regarding my use of collection_select.  Currently, I'm doing this:

<%= form_remote_tag(:update => "ajaxmessage", :url => { :action => :categorise_manually }, :position => "replace" ) %>
  <input id="payment_id" name="payment[id]" type="hidden" value="<%= @payment.id %>" />
  <%= collection_select :payment, :category_id, Category.find(:all, :order => 'name', :conditions => ['for_debits = 1 AND (builtin = 1 OR user_id = ?)', session[:user][:id]]), :id, :name %>
  <%= submit_tag "Set" %>
<%= end_form_tag %></td>

This works nicely.  The user clicks 'Set', and the categorise_manually action is called, and is passed the id of the payment via the hidden parameter, and the id of the category selected from the combo.

However, what I'd like to do is remove the submit_tag, and somehow submit the form immediately the selected value is changed in the combo.  I'm sure this is possible (I've seen it done in GMail for example), I just have no idea how :-(

Yours,
Duncan Bayne

Re: Automatic submit on collection_select change

All you need is the onChange event in your select element.  You can execute any javascript you want when somebody picks a new value.

Actually, I lied.  You'll also need to change your form_remote_tag to a form_tag.  Here's the (untested) code as you'll need it:

 <%= form_tag({:action => :categorise_manually}, {:id => 'my_form'}) %>
   <input id="payment_id" name="payment[id]" type="hidden" value="<%= @payment.id %>" />
   <%= collection_select :payment, :category_id, Category.find(:all, :order => 'name', :conditions => ['for_debits = 1 AND (builtin = 1 OR user_id = ?)', session[:user][:id]]), :id, :name, {}, {:onChange => remote_function(:update => "ajaxmessage", :url => { :action => :categorise_manually }, :position => "replace") } %>
<%= end_form_tag %></td>

Basically what I did is I kept the form tag as a form (so non-js users can still use your site, I took the same options that you gave to form_remote_tag and gave them to remote_function, and I removed the submit tag.
remote_function is a handy thing.  You can see at http://railsmanual.org/module/ActionVie … remote_tag that it's what makes form_remote_tag different from form_tag.  It's useful when you want to make your own custom ajax calls.

Re: Automatic submit on collection_select change

Thanks - I can actually get rid of the form at this point, as the site doesn't have to degrade gracefully in the case of non-js browsers.

However, I'm still stuck :-(  I can't figure out how to use remote_function to pass through the selected category ID, so I've hardcoded it to '1' for the moment, which works:

<%= collection_select :payment, :category_id, Category.find(:all, :order => 'name', :conditions => ['for_debits = 1 AND (builtin = 1 OR user_id = ?)', session[:user][:id]]), :id, :name, {}, {:onChange => remote_function(:update => "ajaxmessage", :url => { :action => :categorise_manually, :payment_id => @payment.id, :category_id => 1}, :position => "replace") } %>

This passes through the following parameters to my controller:
"payment_id" => "370"
"category_id" => "1"

I've done a bit of digging and discovered that I can use the with parameter to specify some javascript to extract the selected value in the combo, but that leads to my controller being passed two parameters, one of which is without a name.  E.g.:
"payment_id" => "370"
"26" => ""

... where in this example 26 is the value of the selected item in the combo.  I can deal with this (iterate through the parameters, extract payment_id, and assume that the first parameter I come across with a numeric name is the category_id), but that's somewhat icky.

I think I'm missing something obvious here ... any suggestions?

Re: Automatic submit on collection_select change

Oh yeah, that part's actually a little counter intuitive.

What you do is you pass a :with argument that contains a little bit of javascript:

   <%= collection_select :payment,
                         :category_id,
                         Category.find(:all, :order => 'name', :conditions => ['for_debits = 1 AND (builtin = 1 OR user_id = ?)', session[:user][:id]]),
                         :id,
                         :name,
                         { :with => "'category_id='+this.value" },
                         {:onChange => remote_function(:update => "ajaxmessage", :url => { :action => :categorise_manually }, :position => "replace") } %>

that one line (:with => "'category_id='+this.value") should send a category_id parameter along with the request.

Re: Automatic submit on collection_select change

Thank you very much - that works perfectly :-)

Re: Automatic submit on collection_select change

Sweet.

You may want to take a look at your code and extract portions of it to a helper. It's a pretty darn big function call :-)