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 %>