Column Visibility
Column Visibility
Column visibility hides and shows columns at runtime, which is what a "choose columns" menu writes. Hidden columns disappear from the column lists, the header groups, and the cells of every row, so a table rendered through the "visible" functions needs no other change. This page ports TanStack Table's Column Visibility (React) Guide.
State
Column visibility owns one state slice: a map from column id to whether that column shows.
-- in Table.State
columnVisibility : Dict String Bool
-- in Table.initialState
columnVisibility = Dict.empty
The map is sparse. A column is hidden only when its id is in the map with the
value False. An id that is absent, or present with True, shows. An empty
map therefore means everything shows, which is why initialState starts
there.
Keys are leaf column ids. A group column has no entry of its own; hiding a group column writes an entry for every hideable leaf below it.
Config options
| Option | Type | Default | Description |
|---|---|---|---|
enableHiding |
Bool |
True |
Turns hiding off for the whole table. With it False, columnCanHide is False for every column. |
Config is a plain record, so you set it with a record update:
{ config | enableHiding = False }.
Column options
| Builder | Type | Default | Description |
|---|---|---|---|
withEnableHiding |
Bool -> Column row -> Column row |
True |
Allow or forbid hiding this column. |
An id column or a row-selection checkbox column is the usual case for
withEnableHiding False:
config : Table.Config Person
config =
Table.config
[ Table.column "id" (.id >> Value.String)
|> Table.withHeader "ID"
|> Table.withEnableHiding False
, Table.column "firstName" (.firstName >> Value.String)
|> Table.withHeader "First name"
, Table.column "lastName" (.lastName >> Value.String)
|> Table.withHeader "Last name"
, Table.column "department" (.department >> Value.String)
|> Table.withHeader "Department"
]
Transitions
| Function | Signature | Description |
|---|---|---|
toggleColumnVisibility |
Config row -> Column row -> Maybe Bool -> State -> State |
Show or hide one column. Nothing flips it. |
setColumnVisibility |
Dict String Bool -> State -> State |
Replace the whole map. |
resetColumnVisibility |
State -> State |
Empty the map, showing every column again. |
toggleAllColumnsVisible |
Config row -> Maybe Bool -> State -> State |
Show or hide every leaf column. Nothing flips on the current state. Columns that cannot hide stay visible. |
The Maybe Bool is TanStack's optional value argument: Just True shows,
Just False hides, Nothing flips.
update : Msg -> Model -> Model
update msg model =
case msg of
ToggleColumn column ->
{ model | state = Table.toggleColumnVisibility config column Nothing model.state }
ToggleAll visible ->
{ model | state = Table.toggleAllColumnsVisible config (Just visible) model.state }
ResetVisibility ->
{ model | state = Table.resetColumnVisibility model.state }
To start with a column already hidden, write the map once:
startHidden : Table.State
startHidden =
Table.setColumnVisibility
(Dict.fromList [ ( "department", False ) ])
Table.initialState
Queries
| Function | Signature | Description |
|---|---|---|
columnIsVisible |
State -> Column row -> Bool |
Does this column show? |
columnCanHide |
Config row -> Column row -> Bool |
May it be hidden? Both the table and the column have to allow it. |
isAllColumnsVisible |
Config row -> State -> Bool |
Is every leaf column visible? |
isSomeColumnsVisible |
Config row -> State -> Bool |
Is at least one leaf column visible? |
visibleLeafColumns |
Config row -> State -> List (Column row) |
The leaf columns to render, in table order. |
visibleFlatColumns |
Config row -> State -> List (Column row) |
Every column, group columns included, minus the hidden ones. |
visibleCells |
Config row -> State -> Row row -> List Cell |
One row's cells whose column is visible, in render order. |
visibleCellsByColumnId |
Config row -> State -> Row row -> Dict String Cell |
The same cells keyed by column id. |
A column menu
columnIsVisible sets the checkbox, columnCanHide disables it, and
toggleColumnVisibility is the message it sends:
viewToggle : Table.State -> Table.Column Person -> Html Msg
viewToggle state column =
label []
[ input
[ type_ "checkbox"
, checked (Table.columnIsVisible state column)
, disabled (not (Table.columnCanHide config column))
, onClick (ToggleColumn column)
]
[]
, text (Maybe.withDefault (Table.columnId column) (Table.columnHeader column))
]
isAllColumnsVisible and isSomeColumnsVisible drive the "toggle all" box at
the top of the list:
viewToggleAll : Table.State -> Html Msg
viewToggleAll state =
label []
[ input
[ type_ "checkbox"
, checked (Table.isAllColumnsVisible config state)
, onClick (ToggleAll (not (Table.isSomeColumnsVisible config state)))
]
[]
, text "Toggle all"
]
viewToggles : Table.State -> Html Msg
viewToggles state =
div []
(viewToggleAll state :: List.map (viewToggle state) (Table.allColumns config))
A visibility-aware body
allColumns and
getAllCells ignore visibility, which
is what you want in a column menu and not what you want in a table body. Use
visibleLeafColumns for the columns and visibleCells for the cells:
viewRow : Table.State -> Table.Row Person -> Html Msg
viewRow state row =
tr []
(List.map
(\cell -> td [] [ text (Value.toString cell.value) ])
(Table.visibleCells config state row)
)
headerGroups and the per-region
header functions already account for visibility, so a header rendered from
them needs no filtering of its own. See
Header Groups.
visibleCells also applies the pinning split: left
cells, then unpinned cells, then right cells.
Not covered
TanStack's page also describes owning the columnVisibility state through the
atoms option or state.columnVisibility plus onColumnVisibilityChange.
There is nothing to port: State.columnVisibility is always yours, held in
your own model.
column.getToggleVisibilityHandler has no counterpart, because the package
produces no event handlers. Write onClick (ToggleColumn column) yourself, as
above.
resetColumnVisibility here is TanStack's resetColumnVisibility(true): it
empties the map. There is no table.initialState to restore, so to go back to
a visibility you started with, call setColumnVisibility with the map you
remembered.
Example
Column Visibility, ported from TanStack's Column Visibility example.