Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mlms13/rr-sortable-table
A generically sortable table with ReasonReact and lenses-ppx
https://github.com/mlms13/rr-sortable-table
Last synced: 25 days ago
JSON representation
A generically sortable table with ReasonReact and lenses-ppx
- Host: GitHub
- URL: https://github.com/mlms13/rr-sortable-table
- Owner: mlms13
- Created: 2019-11-19T23:51:51.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T11:56:20.000Z (almost 2 years ago)
- Last Synced: 2024-04-15T12:13:24.474Z (7 months ago)
- Language: Reason
- Size: 1.12 MB
- Stars: 9
- Watchers: 3
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Reason React Sortable Table
This is an exploration in making a generic Reason React table component. Each row is of some type `'a` (which is probably some product type like a record, but really could be anything). Columns are also defined in a list.
Each column:
- has a title
- uses the title as its React key, but allows overriding the key to avoid collisions
- knows how to extract a value from the row data type
- knows how to render values of that type
- optionally knows how to order values of that type, which will make the column sortableNormally, this would mean that a column is polymorphic (it extracts and renders different types of values from the row data), but that would make it difficult to provide a `list(column('a))` because each column would need to operate on the same type of cell data. Instead, `column` is defined as a GADT with an existential type, so your sort and render functions are type-safe, even though that type isn't represented in the column type.
## Usage
Of note, this is intended to be a source of inspiration more than a ready-to-use library. At the moment, I'm not planning on packaging this up and releasing it on npm, but if you're already using Material UI and want a simple sortable table component, usage looks like this:
```reason
open Relude.Globals;
open BsAbstract;type role = Admin | User;
let roleToString =
fun
| Admin => "Admin"
| User => "User";type user = {
id: string,
name: string,
roles: list(role),
birthday: option(Js.Date.t),
};let rows = [ /* include user records here... */ ];
let columns = [
SortableTable.orderedColumn(
(module String.Ord),
~title="Name",
~render=React.string,
user => user.name,
),
SortableTable.unorderedColumn(
~title="Roles",
~render=
roles =>
roles
|> List.map(roleToString)
|> List.String.joinWith(", ")
|> React.string,
user => user.roles,
),
SortableTable.orderedColumn(
(module Option.Ord(JsDate.Ord)),
~title="Birthday",
~render=bd => Option.fold("-", Js.Date.toString, bd) |> React.string,
user => user.birthday,
)
];[@react.component]
let make = () => user.id} rows columns />;
```The above example assumes you're using the [Relude](https://github.com/reazen/relude) + [bs-abstract](https://github.com/Risto-Stevcev/bs-abstract) libraries. The implementation of `SortableTable` in this project asks orderable columns be constructed with an `Ord` module for the corresponding data type. bs-abstract provides these `Ord` modules for many common types.
But if Relude and bs-abstract aren't your cup of tea, that's fine -- the implementation could absolutely use a "normal" `('a, 'a) => int` function for ordering instead, as is common in the OCaml world. Feel free to hack up this idea until it works for your needs.
Earlier versions relied on [lenses-ppx](https://github.com/Astrocoders/lenses-ppx/) to generate the getters for each column. That has since been simplified away, but the ppx is still very useful, as you can see [in the example](https://github.com/mlms13/rr-sortable-table/tree/master/examples/users).
## Limitations
- Internally, we track the currently-sorted column by its `string` key. This is a bit sad, but since React already complains if you don't provide a unique key, this is a much easier option than requiring the outside world to provide a "column eq" function.
- Material UI may not be for everyone. This approach could be modified to work with basically any table rendering. I happened to pick Material UI because it's easy enough and I didn't want to write CSS.