Reputation: 10460
Consider the following scenario: I have a resource with index
and show
pages in ActiveAdmin
, and on the show page I have more Tabs
.
In some (possibly more than one) of those Tabs
I would like to display information related to the resource in tabular form, with sortable columns.
I would also require the application to stay on the selected Tab
while changing sort order for the tables.
How to achieve this in ActiveAdmin
?
Upvotes: 1
Views: 2094
Reputation: 10460
Unfortunately ActiveAdmin doesn't seem to support this out-of-the-box, but it can be achieved.
in the ActiveAdmin.register
call (usually in lib/admin/resource.rb
) this would create a table for the resource
's some_connection
data:
tab "Tab 2" do
table_for resource.some_connection do
column :name
...
end
end
Unfortunately this is not a sortable table, so we should simply add the following option hash:
{:sortable => true, :class => 'index_table'}
like so:
table_for resource.some_connection, {:sortable => true, :class => 'index_table'} do
Well, this will almost work. Unfortunately selecting a sort column will take you back to the first Tab
, but the sorting will be stored in the URL (in whatever/your/page/address/is?order=name_asc
format).
To solve this issue I monkey-patched ActiveAdmin's
TableFor
class with the following (in a new file I created in my project structure, e.g.: ext/active_admin/views/table_for
):
module ActiveAdmin
module Views
class TableFor
def build(obj, *attrs)
options = attrs.extract_options!
@sortable = options.delete(:sortable)
@collection = obj.respond_to?(:each) && !obj.is_a?(Hash) ? obj : [obj]
@resource_class = options.delete(:i18n)
@resource_class ||= @collection.klass if @collection.respond_to? :klass
@columns = []
@row_class = options.delete(:row_class)
@anchor = options.delete(:anchor)
@sort_key_prefix = ''
@sort_key_prefix = @anchor.to_s + '_' unless @anchor.nil?
build_table
super(options)
columns(*attrs)
end
def build_table_header(col)
classes = Arbre::HTML::ClassList.new
sort_key = sortable? && col.sortable? && col.sort_key
params = request.query_parameters.except :page, :order, :commit, :format
classes << 'sortable' if sort_key
classes << "sorted-#{current_sort[1]}" if sort_key && current_sort[0] == @sort_key_prefix + sort_key
classes << col.html_class
if sort_key
th class: classes do
link_to col.pretty_title, params: params, order: "#{@sort_key_prefix}#{sort_key}_#{order_for_sort_key(@sort_key_prefix + sort_key)}", anchor: @anchor
end
else
th col.pretty_title, class: classes
end
end
end
end
end
Basically I added an anchor parameter in options, and using this we can get back to the tab where the table is after selecting a sort criteria. Those criteria's name are extended with this anchor as a prefix, so having columns named the same in different tabs would not mess up the sorting of the different tables. (Currently I use the anchor as the prefix, but this could be changed to a fully separate option parameter to support more tables in one Tab
)
I use an initializer to load the monkey patch, which simply requires the file which contains the code from above (ext/active_admin/views/table_for
in my example):
monkey_patches.rb
-----------------
require 'ext/active_admin/views/table_for'
These changes require us to slightly modify the way we build the table (we have to retrieve the sort settings from the params
and apply them to our data):
tab_name = "Tab 2"
tab tab_name do
tab_anchor = tab_name.parameterize('_')
data = resource.some_conection
unless params['order'].nil?
order = params['order'].to_s.sub(tab_anchor + '_', '').sub("_asc", " ASC").sub("_desc", " DESC")
data = data.order(order) unless order.nil?
end
table_for data, { anchor: tab_anchor, :sortable => true, :class => 'index_table'} do
column :name
...
end
end
This is the result (here the table is actually put into a Panel
, and the anchor
points to that):
Upvotes: 4
Reputation: 5125
Actually, ActiveAdmin does support this.
To sort the table, call the order()
method and pass the column name and either desc/asc
, like do:
table_for boat.bookings.order('created_at desc') do
column :name
column :created_at
end
Thanks to Ryan Bates' screencast: http://railscasts.com/episodes/284-active-admin?view=asciicast
Upvotes: -1