DataTable renders collections (an array of hashes or ActiveRecord models) as HTML tables.
gem install data-table
or, in your Gemfile
gem 'data-table'
the normal usage is to call the DataTable.render()
method and pass it a collection. The method also takes a block which can be used to configure the table. The column method takes a symbol for the first parameter. If the symbol matches a key in the @collection, then that value is printed in the cell.
DataTable.render(@collection) do |t|
t.column :column_1, "Title"
t.column :column_2, "Title 2"
end
Sometimes you want to use Ruby code to customize the value for a cell. This can be done by passing a block to the .column method
DataTable.render(@collection) do |t|
t.column :column_id, "Title" do |value, row, row_index, column, column_index|
"The value is: #{value}"
end
end
You don't need to pass in all of the block parameters; just the ones up to the one you need.
Tip The column_id doesn't need to be an actual key in the collection. You can just make up an arbitrary column id and use the block renderer to customize the value for a column.
id: the html id
title: the title of the data table
subtitle: the subtitle of the data table
css_class: an extra css class to get applied to the table
empty_text: the text to display of the collection is empty
display_header => false: hide the column headers for the data table
alternate_rows => false: turn off alternating of row css classes
alternate_cols => true: turn on alternating of column classes, defaults to false
It is possible to setup totals & subtotals. Total columns take the name of the column that should be totaled. It is also possible to specify multiple total and subtotal columns.
They also take a default aggregate function name and/or a block.
- If only a default function is given, then it is used to calculate the total
- If only a block is given then only it is used to calculated the total
- If both a block and a function are given then the default aggregate function is called first then its result is passed into the block for further processing.
DataTable.render(@collection) do |t|
t.column :column_1, "Title"
t.column :column_2, "Title 2"
t.column :column_3, "Title 3"
# Use a default function and no block.
t.total :column_1, 0, :sum
# Pass only a block and an index
t.total :column_2, 1, do |values|
# custom methods here
end
# Pass a default function and a block
t.total(:column_3, 2, :sum) do |aggregate_total|
format_money(aggregate_total)
end
end
Possible default functions: :sum
, :avg
, :min
, :max
SubTotals work in a similar way to Totals. The main difference is that you need to call group_by to specify the different subtotal groupings.
When configuring more than one subtotal column the index parameter is required
DataTable.render(@collection) do |t|
t.column :column_1, "Title"
t.column :column_2, "Title 2"
t.column :column_3, "Title 3"
t.column :column_4, "Title 4"
t.group_by :column_1
t.subtotal :column_2, 0, :sum
t.subtotal :column_3, 1, :max
end
It is possible to use group_by
on its own without subtotaling.
It is also possible to combine multiple group_by
with multiple subtotal
. In this
scenario you must specify a level
for each group by passing an integer value.
When only specifying a group you may omit level
.
DataTable.render(@collection) do |t|
t.column :column_1, "Title"
t.column :column_2, "Title 2"
t.column :column_3, "Title 3"
t.group_by :column_1, 0
t.group_by :column_2, 1
t.subtotal :column_3, 0, :sum
t.subtotal :column_3, 0, :sum
end
You can also combine subtotals & totals in the same table.
Nearly all of the code for this was written by @smerickson, and later gemified by @sixfeetover.