Skip to content

Instantly share code, notes, and snippets.

@markahesketh
Created April 25, 2024 13:43
Show Gist options
  • Save markahesketh/3f63b17fd5b4469adf69fae00bff9bf2 to your computer and use it in GitHub Desktop.
Save markahesketh/3f63b17fd5b4469adf69fae00bff9bf2 to your computer and use it in GitHub Desktop.
ViewComponent Table Example
class Admin::DataTable::CellComponent < ApplicationComponent
def initialize(tag: :td, header: false, collapse: false, padding: true, numeric: false, centered: true, **args)
@args = args
@args[:tag] = tag
@args[:class] = class_names(
@args[:class],
"text-end" => numeric,
"w-1" => collapse,
"text-center" => centered,
"py-0" => !padding
)
end
def call
component_tag(**@args) do
content
end
end
end
class Admin::DataTable::ColumnComponent < LegacyApplicationComponent
attr_reader :title, :numeric, :padding, :centered, :collapse, :args
def initialize(title, collapse: false, numeric: false, padding: true, centered: false, **args, &cell)
@title = title
@collapse = collapse
@numeric = numeric
@padding = padding
@centered = centered
@args = args
@cell = cell
end
def call(row)
@cell.call(row)
end
end
<%= component_tag(class: "table-responsive") do %>
<table class="table table-vcenter card-table">
<thead>
<tr>
<% columns.each do |column| %>
<%= render_cell(
tag: "th",
header: true,
collapse: column.collapse,
numeric: column.numeric,
centered: column.centered,
) do %>
<%= column.title %>
<% end %>
<% end %>
</tr>
</thead>
<tbody>
<% @data.each do |row| %>
<tr>
<% columns.each do |column| %>
<%= render_cell(
numeric: column.numeric,
centered: column.centered,
collapse: column.collapse,
padding: column.padding,
) do %>
<%= column.call(row) %>
<% end %>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<% end %>
class Admin::DataTableComponent < ApplicationComponent
renders_many :columns, ->(title, **args, &block) do
Admin::DataTable::ColumnComponent.new(title, **args, &block)
end
def initialize(data, **attributes)
@data = data
@attributes = attributes
end
def render_cell(**, &block)
render(Admin::DataTable::CellComponent.new(**), &block)
end
end
...
<%= render Admin::DataTableComponent.new(@baskets) do |table| %>
<% table.with_column("Date") do |basket| %>
<%= link_to basket.created_at.to_fs(:long_date), admin_basket_path(basket.id), class: "fw-bold" %>
<% end %>
<% table.with_column("Email") do |basket| %>
<%= basket.email || "-" %>
<% end %>
<% table.with_column("Delivery method") do |order| %>
<%= order.delivery_method&.name || "-" %>
<% end %>
<% table.with_column("Status", collapse: true) do |order| %>
<%= basket_status_badge(order) %>
<% end %>
<% table.with_column("Items", numeric: true) do |basket| %>
<%= basket.quantity %>
<% end %>
<% table.with_column("Items Price", numeric: true) do |basket| %>
<%= number_to_currency basket.lines_price, unit: "£" %>
<% end %>
<% table.with_column("Total", numeric: true) do |basket| %>
<%= number_to_currency basket.total_price, unit: "£" %>
<% end %>
<% table.with_column("Actions", collapse: true) do |basket| %>
<%= link_to "View", admin_basket_path(basket.id) %>
<% end %>
<% end %>
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment