view component table
I have been trying ViewComponent for the UI in an application I wrote.
It has been great improvement for testing the little bits of the UI as well as many of other benefits.
It took me a while to figure out the best way to do a table using the gem, so I am noting my solution here.
First I need to create a component using the following files:
app/components/table_component.rb
class TableComponent < ApplicationComponent
renders_many :headings
renders_many :rows, TableRowComponent
end
app/components/table_component.html.erb
<table class="table align-middle table-striped listing">
<thead class="table-primary">
<tr>
<% headings.each do |heading| %>
<th> <%= heading %> </th>
<% end %>
</tr>
</thead>
<tbody>
<% if !rows? %>
<tr>
<td scope="row" colspan="100%">
<i>Empty</i>
</td>
</tr>
<% else %>
<% rows.each do |row| %>
<%= row %>
<% end %>
<% end %>
</tbody>
</table>
app/components/table_row_component.rb
class TableRowComponent < ApplicationComponent
renders_many :columns
def initialize(item:)
@item = item
end
attr_reader :item
end
app/components/table_row_component.html.erb
<tr>
<% columns.each do |col| %>
<td> <%= col %> </td>
<% end %>
</tr>
With the component in place I can now use it in a template to render, for example, a table of users with delete buttons.
<%= render(TableComponent.new) do |table| %>
<% table.with_heading { "Name" } %>
<% table.with_heading { "Organisation" } %>
<% table.with_heading { "" } %>
<% users.each do |item| %>
<% table.with_row(item: item) do |row| %>
<% row.with_column { row.item.name } %>
<% row.with_column { row.item.organisation.name } %>
<% row.with_column do %>
<%= render DeleteButtonComponent.new(path: users_path(row.item)) %>
<% end %>
<% end %>
<% end %>
<% end %>