Table

Renders a simple table.

Read more Read less

Maturity: Developing

Usage

<.table id="pets" rows={@pets} caption="Pets">
  <:col :let={p} label="name"><%= p.name %></:col>
  <:col :let={p} label="age"><%= p.age %></:col>
</.table>

Row actions

row_click sets phx-click on each cell, which reaches pointer users only. Where you use it, repeat the action as a link or button inside the row, so that it can also be reached by keyboard.

<.table
  id="pets"
  rows={@pets}
  caption="Pets"
  row_click={&JS.navigate(~p"/pets/#{&1}")}
>
  <:col :let={p} label="name">
    <.link navigate={~p"/pets/#{p}"}><%= p.name %></.link>
  </:col>
</.table>

Scroll container

The div around the table has tabindex="0", so that a table that is wider than its container can be scrolled using the keyboard. This assumes that you make the container scrollable:

.table-container {
  overflow-x: auto;
}

Set caption or label to name the container, which is then exposed as a region. A blank value counts as unset.

If the table fits its container, or sits in another scroll container, set scrollable={false}. The wrapper then has no tabindex, no role and no name, and does not add a useless tab stop.

NameBreedAgeSexWeightColourMicrochipVaccinatedNeuteredShelterArrivedOwnerEmailPhoneLicenceStatus
George Dachshund 8 Male 9.2 kg Black and tan 981020012345678 2026-03-14 Yes Bergedorf Animal Shelter 2025-11-02 Katrin Dinkelschrot katrin.dinkelschrot@example.com +49 40 123456 HH-2025-004871 Available
Mary Golden Retriever 5 Female 28.6 kg Cream 981020087654321 2026-01-27 No Altona Rescue Centre 2026-02-19 Hendrik Vollmerhausen hendrik.vollmerhausen@example.com +49 40 654321 HH-2026-001294 Reserved
Attribute Type Documentation Default Value
caption :string

Content for the <caption> element.

class :any

Any additional classes to be added.

Read more Read less
[]

Variations of the component should be expressed via modifier attributes, and it is preferable to use styles on the parent container to arrange components on the page, but if you have to, you can use this attribute to pass additional utility classes to the component.

The value can be a string or a list of strings.

Required id * :string
label :string

Names the scroll container, which is in the tab order so that the table

Read more Read less

can be scrolled by keyboard.

If not set, the caption is used to name the container. A scrollable container needs one of the two.

rest :global

Any additional HTML attributes.

row_click :any

Sets the phx-click function attribute for each row td. Expects to be

Read more Read less

a function that receives a row item as an argument. This does not add the phx-click attribute to the action slot.

This is a pointer convenience only. A td is not focusable, has no interactive role and takes no key events, so the action is unavailable to keyboard and screen reader users. Every action reachable through row_click must therefore also be reachable from a link or button inside the row, in a :col or :action slot.

Example:

<.table id="users" rows={@users} row_click={&JS.navigate(~p"/users/#{&1}")}>
  <:col :let={user} label="Name">
    <.link navigate={~p"/users/#{user}"}>{user.name}</.link>
  </:col>
</.table>
row_id :any

Overrides the default function that retrieves the row ID from a stream

Read more Read less

item.

row_item :any

This function is called on the row item before it is passed to the :col

Read more Read less
&Function.identity/1

and :action slots.

Required rows * :list

The list of items to be displayed in rows.

scrollable :boolean

Puts the container in the tab order and exposes it as a named region,

Read more Read less
true

so that a table wider than its container can be scrolled by keyboard. Set it to false for a table that fits its container.

action :slot

The slot for showing user actions in the last table column. These columns do not receive the row_click attribute.

<:action :let={user}>
  <.link navigate={~p"/users/#{user}"}>Show</.link>
</:action>
Show slot attributes Hide slot attributes
label :string

The content for the header column.

col_attrs :list

If set, a <colgroup> element is rendered and the attributes are added to the <col> element of the respective column.

Required col * :slot

For each column to render, add one <:col> element.

<:col :let={pet} label="Name" field={:name} col_style="width: 20%;">
  <%= pet.name %>
</:col>

Any additional assigns will be added as attributes to the <td> elements.

Show slot attributes Hide slot attributes
label :any

The content for the header column.

col_attrs :list

If set, a <colgroup> element is rendered and the attributes are added to the <col> element of the respective column.

<:col :let={p} label="Name"><%= p.name %></:col>
<:col :let={p} label="Breed"><%= p.breed %></:col>
<:col :let={p} label="Age"><%= p.age %></:col>
<:col :let={p} label="Sex"><%= p.sex %></:col>
<:col :let={p} label="Weight"><%= p.weight %></:col>
<:col :let={p} label="Colour"><%= p.color %></:col>
<:col :let={p} label="Microchip"><%= p.chip %></:col>
<:col :let={p} label="Vaccinated"><%= p.vaccinated %></:col>
<:col :let={p} label="Neutered"><%= p.neutered %></:col>
<:col :let={p} label="Shelter"><%= p.shelter %></:col>
<:col :let={p} label="Arrived"><%= p.arrived %></:col>
<:col :let={p} label="Owner"><%= p.owner %></:col>
<:col :let={p} label="Email"><%= p.email %></:col>
<:col :let={p} label="Phone"><%= p.phone %></:col>
<:col :let={p} label="Licence"><%= p.licence %></:col>
<:col :let={p} label="Status"><%= p.status %></:col>
foot :slot

You can optionally add a foot. The inner block will be rendered inside a tfoot element.

<Flop.Phoenix.table>
  <:foot>
    <tr><td>Total: <span class="total"><%= @total %></span></td></tr>
  </:foot>
</Flop.Phoenix.table>