I love Ajax.InPlaceEditor, cause it allows me quickly edit a field by just clicking on the text value. If you have used Flickr, I am pretty sure you know what I meant.

It is easy to create an in-place-editor if you are using Ruby On Rails (RoR).

  # Controller
  class BlogController < ApplicationController
    in_place_edit_for :post, :title
  end

  # View
  <%= in_place_editor_field :post, 'title' %>

Problem

The problem with InPlaceEditor is when you enter an empty value, you lost the text where you can click to edit.

One way is to extend Ajax.InPlaceEditor to display “click to edit…” text if the value is empty.

But on some cases, that is not what you want. For example if the text field is a numeric value, you would want your model class to peform the ActiveRecord validation and display the validation message if user enters an invalid value. And you probably would not want to re-code the validation rules in Javascript.

Solution

This is a hack that extends ActiveController::Base to include an additional class method in_place_edit_with_validation_for, which basically displays an alert box containing the model error messages is it is not valid.

And this is how you go about doing it:

  1. Create custom_in_place_editing.rb and save it in [app_root]/lib directory.
    module ActionController
      module Macros
       module CustomInPlaceEditing
        def self.included(base)
         base.extend(ClassMethods)
        end
       
        module ClassMethods
         def in_place_edit_with_validation_for(object, attribute)
          define_method("set_#{object}_#{attribute}") do
           klass = object.to_s.camelize.constantize
          @item = klass.find(params[:id])
          @item.send("#{attribute}=", params[:value])
           if @item.save
            render :update do |page| 
             page.replace_html("#{object}_#{attribute}_#{params[:id]}_in_place_editor", 
             @item.send(attribute))
            end
           else
            render :update do |page|
             page.alert(@item.errors.full_messages.join("\n"))
             klass.query_cache.clear_query_cache if klass.method_defined?:query_cache
             @item.reload
             page.replace_html("#{object}_#{attribute}_#{params[:id]}_in_place_editor", 
             @item.send(attribute))
            end
           end
          end
         end
        end
       end
      end
    end
    
    ActionController::Base.class_eval do
      include ActionController::Macros::CustomInPlaceEditing
    end
    
  2. Update the following files accordingly:
       # Controller file
       class ProductController < ApplicationController
         in_place_edit_with_validation_for :product, :price
       end
       
       # View file, remember to set the :script option to true
       # Rails 1.2.3
       <%= in_place_editor_field :product, :price, :script => true %>
    
       # Rails on edge
       <%= in_place_editor_field :product, :price, {}, :script => true %>
    
       # [app_root]/config/environment.rb 
       require 'custom_in_place_editing'
    
  3. Restart your server instance.

And that’s it, there is no other step, you are done.

21 Comments . Comments Feed . Trackback URI
Tue, 20 Mar 07 09:56 pm . Dr Nic wrote:

Nice work (I say that prior to testing… :)

Now, lazy man, lets see this in a plugin. Ok, I’ll be the lazy man, perhaps.

Tue, 20 Mar 07 10:25 pm . Herryanto Siatono wrote:

Thanks Dr. Nic, yeah…a plugin would be nice….will wrap it up soon. :)

Mon, 23 Apr 07 06:15 am . Jeff wrote:

Nice work — thanks for sharing it. I have found a little wrinkle though. Suppose I have a field for which I do want to by-pass validations. If I specify in_place_edit_for :product, :price in my controller, then when I click ok in the view, the edit is performed, but the page is not refreshed afterward — the “Saving…” message doesn’t go away.

Mon, 23 Apr 07 06:16 am . Jeff wrote:

Sorry, please cancel the previous post. The reason I was not getting the refresh on the on the in_place_edit_for field is that I included the :scripts => true parameter in my view. Once I removed it, thiings worked fine.

Mon, 23 Apr 07 08:17 am . Herryanto Siatono wrote:

Ok. :)

Tue, 4 Sep 07 11:04 pm . Rene wrote:

I’m a bit of a rails newbie, but I was wondering how one passes the :options hash to your validating in_place_editor_field as if they were using the original scriptaculous in_place_editor_field. Eg-

in_place_editor_field :model,
:attr,
{},
{ :okText => ‘”Save”‘ }

I can’t seem to get the parameters’ syntax correct now that the :script => true is present.

Wed, 5 Sep 07 09:01 am . Herryanto Siatono wrote:

Ic, I guess you are confused with the usage on Rails 1.2.3 and Rails on edge. My example is based on rails on edge, will update it accordingly.

For rails 1.2.3:
===========
in_place_editor_field(object, method, in_place_editor_options={})

Example:
————-
in_place_editor_field [model], [attr], :script => true, :okText => ‘”Save”‘

For Rails on edge:
==============
in_place_editor_field(object, method, tag_options={}, in_place_editor_options={})

Example:
————-
in_place_editor_field [model], [attr], {}, :script => true, :okText => ‘”Save”‘

Fri, 7 Sep 07 07:29 pm . mb wrote:

Hi, This works for me and catches invalid data that I enter in the field. However, if I hit the reload button after that, the invalid data gets stored in the database. It is because the reload generates a get call and so it doesn’t get routed through your set_model_attr method.

Fri, 7 Sep 07 07:44 pm . mb wrote:

But, I thought restful routing shouldn’t update the database with get calls???

Sat, 8 Sep 07 12:35 am . mb wrote:

Nope.There was a problem with my validations and I fixed it. Now it works fine.

Tue, 16 Oct 07 01:07 pm . Mario wrote:

Is there anyway to combine this with a way to use the :highlightcolor or highlightendcolor?

Perhaps a way to combine it with in_place_editor_ext from http://www.ruby-forum.com/topic/86680#161018

Thanks!

-rails newb

Tue, 16 Oct 07 02:21 pm . Herryanto Siatono wrote:

@Mario, I’ve checked rails documentation, in_place_editor_field doesn’t support highlightcolor and highlightcolorend options, you probably need to use in_place_editor_ext, and just pass in the two options.

It should be transparent with in_place_edit_with_validation_for.

Fri, 23 Nov 07 08:59 pm . santu wrote:

I have done the abouve process for in_place_edit validation everything fine

It is giving the alret box on my validation but it is automatically stroing or updating with the following text

” try { alert(”Name has already been taken”); Element.update(”filter_name_1_in_place_editor”, “–None–”); } catch (e) { alert(’RJS error:\n\n’ + e.toString()); alert(’alert(\”Name has already been taken\”);\nElement.update(\”filter_name_1_in_place_editor\”, \”–None–\”);’); throw e }”

Could u give me any ideas?

Thu, 29 Nov 07 07:55 pm . Paul wrote:

@santu:

i stumbled upon the same. (prototype 1.6.0, scriptaculus 1.8.0)
After a few hours of code review i found a workaround. I do not have the time to track down the bug itself, but it seems to me that prototype does not properly respect the js content-type header in this case.

Add

Ajax.InPlaceEditor.DefaultOptions.htmlResponse = false;

after the inclusion of prototype and scriptaculus.

best
paul

Wed, 16 Apr 08 03:12 pm . mahesh wrote:

its very nice,

if we have used the in_place_editor_field for one field while editing the data by clicking on ok. its working fine. when i am submitting the field without giving data the validations are working by popup. along with name field it is displaying all the error messages for the model.

how can we make to display the error message for only one field.

Fri, 9 May 08 12:17 am . Nick wrote:

Thanks, this works quite well. Does anybody know of a way to include something like an image next to the editable text, so that the user knows its editable? This would also need to be nested within the link.

Thanks!

Thu, 24 Jul 08 02:46 am . Paul L wrote:

@ Paul

Thank you so much for that tip, I’ve been going nuts trying to work out why the my javascript was being displayed and not executed.

Paul

Wed, 3 Dec 08 04:24 pm . suresh wrote:

I have done the aboue process for in_place_edit validation everything fine

It is giving the alret box on my validation but it is automatically stroing or updating with the following text

” try { alert(”Name has already been taken”); Element.update(”filter_name_1_in_place_editor”, “–None–”); } catch (e) { alert(’RJS error:\n\n’ + e.toString()); alert(’alert(\”Name has already been taken\”);\nElement.update(\”filter_name_1_in_place_editor\”, \”–None–\”);’); throw e }”

plz help me out from this. i am getting this bug whenevr i try to
press ok

Fri, 16 Jan 09 11:01 pm . Brian Getting wrote:

Anyone have any ideas why the :external_control option doesn’t seem to work with this?

Otherwise this works great. The :save_text option works, but the :external_control does not.

Sat, 17 Jan 09 02:21 am . Brian Getting wrote:

Nevermind. It turns out that you have to put the external control element (a div or something) in a particular place. I had it directly after the “in_place_editor_field” method in my template, but it would not take. Moving it out of the same paragraph seems to work.

My fault, it has nothing to do with your code!

Tue, 16 Jun 09 08:53 pm . Gudata wrote:

If you have some errors in production environment you could try to move
custom_in_place_editing.rb in the config/initializers directory.

Add Your Comment



(optional)