Tuesday, November 21, 2006

Using Rails in_place_editor and in_place_editor_field

In-place form editing is the first Recipe in the Rails Recipes book, and for good reason. Our application has a screen on which the user enters a dollar amount, from which several other amounts are calculated and displayed for review. A user typically cycles through this process 2 or 3 times before being ready to save their results.

The in_place_editor_field (or in_place_editor) provides a clean solution for this need. The user can click the amount to edit, click ok to submit it (while remaining on the page), and review the calculated results.

I coded the view using in_place_editor_field (which uses parameters identical to text_field - send it your object and column to be edited, and you're in business). In our case, the model object is named coverage, and the field to be edited is annual_amount, so the view contains:

<%= in_place_editor_field('coverage', 'annual_amount') %>

The user can now click the amount, edit it in place, and click OK to submit the results.

To process the results (since we wanted to do some calculations, rather than just saving the entry), we are responsible for providing a controller method (named appropriately as it is automatically called when the user submits their edit) as follows:

def set_coverage_annual_amount
#store posted amount
#(available in params[:value] )
#and/or use the results in calculations

The params[:value] that was automatically submitted to the method, so I did my calculations based on the submitted value. A more typical use is to store the submission, but in my case that was deferred until final form submission.

Finally, one the results are submitted and processed, the controller method wants a corresponding view to render its results. In this case, an rjs template was the way to go, so I created the view set_coverage_annual_amount.rjs with just one line of code:

page.replace_html 'amounts_group',
:partial => 'subscriber_amounts'

The subscriber_amounts partial form was already available, displayed all of the recalculated fields, and was just as easy to re-render as opposed to updating each individual field in the rjs template (which would have worked just as well). What did not work was attempting do do the partial render directly within the controller's set_coverage_annual_amount method - this resulted in the edited amount field being replaced with the entire 'amounts_group' div contents.

If you need similar functionality on any piece of data, in_place_editor works in a similar fashion. You display a piece of data identifiable via the DOM (such as by using the span tag with an ID - for this example the ID is 'myamount'). Then follow up with in_place_editor in the same view to mark the item with the necessary AJAX goodness:
<%= in_place_editor('myamount',   
{:url => url_for(
:action => "set_coverage_annual_amount")}) %>
Note quite as pretty as in_place_editor_field, as you have to explicitly identify the destination the edit will be posted to, but the capability is still nice to have when you need it.

See the Rails wiki, Shoo.gr, and Shane's Brain Extension for other articles (in addition to the Rails API reference and the Rails Recipes book) that I found particularly helpful on this topic.


Denise said...

I didn't have trouble doing the update in the Controller, but I had to use page.replace instead of page.replace_html.

Denise said...

Thanks for this article, by the way. Couldn't find much else on this subject and this was very clear and easy to understand.