Ruby on Rails
observe_field - Passing Parameters

Passing the default parameter

<input id="search" name="search" type="text" value="">
<%= observe_field 'search',  :frequency => 0.5, 
         :update => 'target_id', :url => 
         { :controller => '<controller>', :action=> 'list' }, 
         :with => "'search=' + escape(value)" %>

Passing multiple parameters

<select name="section" id="section">
     <option value="docs">Documentation</option>
     <option value="pr">Press Releases</option>
</select>
<input id="search" name="search" type="text" value="">
<%= observe_field "search",
     :url => {:controller => "search", :action => "list"},
     :with => "'section='+ escape($('section').value) + '&search=' + escape(value)",
     :update => "search_results" %>

To answer an earlier question here: Each parameter passed in should be escaped. Otherwise, the right sequence of characters can create additional parameters. While probably not a security risk, it’s good practice and guarantees the users’ input will be passed in full.

Another Way

I couldn’t get the above example to work…perhaps due to the fact that I was using the Rails Form Helpers and not the HTML Form tags. A little research into the prototype.js documentation I found at Particletree helped me come up with the following:

<%= observe_field("field1",
  :frequency => 1,
  :update => "span1",
  :url => {:action => :calculate_total},
  :with => "'values='+escape(value) + ' ' + $F('field2')") %>

I used the $F function from the prototype library to add the value of the additional field. In my controller, the ‘values’ string from the :with argument is passed into params[:values]. I can then use string manipulators (which is why I added the space between the two field values) to access the values I need to perform the server side operations and then render them in the partial(s) I choose. Like so:

def calculate_total
  a = params[:values]
  i = a.split[0].to_i
  i2 = a.split[1].to_f
    
  i2 = i2/100
  cv = i - (i*i2)
        
  render :text => cv.to_s
end

Hope this helps someone…

Yet Another Way

Here is another way to pass multiple parameters documented here. Using Prototype Form.serializeElements() function, you can achieve the same thing, and it has the advantages of preserving the params key assigned to the html elements if they are created using form_for or fields_for.


observe_field :target_dom_id,
      :url => some_named_route_url,
      :method => :get,
      :with => "Form.serializeElements($('text_field_one', 'text_field_two', ...))"

Default method

Don’t forget that simply doing this:

<%= observe_field("field1",
  :frequency => 1,
  :update => "span1",
  :url => {:action => :calculate_total},
  :with => "stuff") %>

will put the current value of ‘field1’ into params[:stuff] accessible to your RJS templates. But, be warned that if the field contains an ampersand (&), more than one params element may be passed. For example, if in field1 an end user typed in “hello&hi=greetings”, then

params[:stuff]"hello"
params[:hi]“greetings”

This is usually not the desired behavior, so you’ll probably want to use
:with => “‘stuff=’+escape(value)”
which, in this example, will result in
params[:stuff]==“hello&hi=greetings”

Escaping ≠ no problems

While i solved the &-problem using

:with => "'value='+escape(value)"

it still fails to submit ‘+’-signs.

First i considered a client and server solution (replacing on client and back-replacing on server) but after reading that the escape-method is depreciated i tried the alternatives and this works well for me:

  :with => "'value='+encodeURIComponent(value)"

Identical Format to a Form Submit

If you’re using something like

<%= password_field "user", "password", :size => 20, :value=>"" %>

to create your form and would like to have a partial ajax submit through an observe_field call to have the same format as the final full form submit then use this format. ie. here combined password and password confirmation.

<%= observe_field "user_password_confirmation",
                 ...
                 :with => "'user[password_confirmation]=' 
                           + encodeURIComponent(value) 
                           + '&user[password]=' 
                           + encodeURIComponent($('user_password').value)" %>