Following from my earlier post on making icon buttons, I needed to add AJAXy goodness to the edit actions on one of our index pages.... but I still wanted cute little icons to make them look pretty.
So I've updated the code to incorporate an icon_button_to_remote method. Note that icon_button_to has also been modified, but it still depends upon the get_icon_path and fixed_button_to methods from the previous post.
# generates appropriate image-buttons, given an "icon type" and the usual # button options. def icon_button_to(icon_type, icon_label, form_opts = nil, button_opts = {}) unless form_opts.blank? button_opts.merge!(:type => 'image', :src => get_icon_path(icon_type), :alt => icon_label, :title => icon_label) the_icon = fixed_button_to(icon_label, form_opts, button_opts) else # no form was passed in - we want a non-linked icon. the_icon = image_tag(get_icon_path(icon_type), :width => 16, :height => '16', :alt => icon_label, :title => icon_label) end content_tag 'div', the_icon, :class => 'icon_button' end # add a remote AJAX-linked icon button def icon_button_to_remote(icon_type, icon_label, remote_options = {}, button_options = {}) link_to_remote(icon_button_to(icon_type, icon_label, nil, button_options), remote_options) end
The example would be for an index page with a list of Widgets. Each one has an "edit" button using the code below. The page also has a section for entering a new widget - which would be replaced by the "edit this widget" template when you click on the icon.
<!-- In the template at the top of the list --> <%= w_path = new_widget_path() # url_for is slow icon_button_to_remote( :new, 'Add new widget', :update => 'new_widget_div', :url => w_path, :method => :get, :html => {:href => w_path}, :complete => "Element.hide('edit_widget_div'); Element.show('new_widget_div'); new Effect.Highlight('new_widget_div');" ) -%> <!-- and next to each widget --> <%= ew_path = edit_widget_path(@widget) # url_for is slow icon_button_to_remote( :edit, 'Edit this widget', :update => 'edit_widget_div', :url => ew_path, :method => :get, :html => {:href => ew_path}, :complete => "Element.hide('new_widget_div'); Element.show('edit_widget_div'); new Effect.Highlight('edit_widget_div');" ) -%> <!-- Later in the template... --> <div id="new_widget_div">New widget form would go here</div> <div id="edit_widget_div" style="display:none;">Edit widget form will be populated here</div>
You also have to update your Controller code for the new and edit actions to accept js and respond with no layout - otherwise your div gets populated with the entire edit/new page :P
The best way is to move the meat of the page into a partial (which can also be loaded in the edit.rhtml template) callable from the action thus:
def edit respond_to do |format| format.js { return render(:partial => 'edit', :layout => false) } format.html # edit.rhtml end end