Sortabular - Sort utilities
Sortabular's helpers make it possible to manage sorting related classes and to sort rows based on them.
API
The API consists of the sort helpers, transforms, formatters, and strategies. These can be combined together to set up sort in various ways. There's control over the algorithm used as well as how it's bound to the user interface. You can also control how sorting is tracked (per column index or per property).
; // Or you can cherry-pick;;
Helpers
sort.byColumn({ sortingColumns: <sorting columns>, sortingOrder: {FIRST: <string>, <string>: <string>}, selectedColumn: <string> }) => <sorting colums> || {}
sort.byColumn
allows you to sort per one column. It discards possible existing sorting state. If you are trying to sort the same column, it will cycle between ascending, descending, and no sorting. In case you are trying to sort some other column, it will start from the ascending state while discarding the existing sorting state.
sort.byColumns({ sortingColumns: <sorting columns>, sortingOrder: {FIRST: <string>, <string>: <string>}, selectedColumn: <string> }) => <sorting columns> || {}
sort.byColumns
is like sort.byColumn
except it doesn't discard possible existing sort state and instead accumulates it. This allows you to perform sorting over multiple columns while refining the results. The last-sorted column always has the highest position
value, i.e. the lowest sorting priority.
sort.byColumnsPrioritizeLastSorted({ sortingColumns: <sorting columns>, sortingOrder: {FIRST: <string>, <string>: <string>}, selectedColumn: <string> }) => <sorting columns> || {}
sort.byColumnsPrioritizeLastSorted
is like sort.byColumns
except it
always gives the last-sorted column the highest sorting priority.
sort.sorter({ columns: [<object>], sortingColumns: <sorting columns>, sort: <function>, strategy = strategies.byIndex })([<rows to sort>]) => [<sorted rows>]
sort.sorter
sorts the passed rows
using a sortingColumns
definitions and a sort
function. It has been designed to work based on lodash.orderBy signature.
If you want to evaluate columns in a reverse order instead of the default, you can reverse sort
function like this:
const reverseSort = ;
Transforms
sort.sort = ({ event = 'onClick', getSortingColumns = () => [], strategy = strategies.byIndex, onSort = (columnIndex) => {} } = {}) => (value, { columnIndex }, props)
sort.sort
can be applied as a transform. It expects getSortingColumns
and onSort
callbacks. The former should return the sorting column data, the latter is called when the user sorts based on event
.
sort.reset = ({ event = 'onDoubleClick', getSortingColumns = () => [], strategy = strategies.byIndex, onReset = (columnIndex) => {} } = {}) => (value, { columnIndex }, props)
sort.reset
can be applied as a transform. It expects getSortingColumns
and onReset
callbacks. The former should return the sorting column data, the latter is called when the user sorts based on event
.
Formatters
sort.header = ({ sortable, strategy = strategies.byIndex, getSortingColumns = () => [] }) => (value, { columnIndex })
sort.header
can be used to sort within a header cell. This works well with sort.reset
since then you can apply both reseting and sorting to the same cell without conflicts. It expects an initialized sortable (i.e., sort.sort
) and getSortingColumns
. If sorting is active at a column, it displays the current order number.
sortable
and strategy
parameters are optional. getSortingColumns
is required.
You can customize props
of sort.header
specific portions through the following protocol:
props = container: {} value: {} order: {}
sort.order = ({ strategy = strategies.byIndex, getSortingColumns = () => [] }) => (value, { columnIndex })
sort.order
can be used to display a sorting arrow widget. It figures out the class name based on the current sorting status. sort.header
uses this internally.
Strategies
Most of the functions accept a strategy. This allows you to modify their sorting behavior. By default they'll track sorting by column index. It's possible to change it to sort by property.
sort.strategies.byIndex
byIndex
is the default strategy used by other functions. It literally means the system will track sorting per index.
sort.strategies.byProperty
byProperty
ties sorting state to column property. This can be useful if you want to retain the sorting state within a column while moving it around.
Sorting Protocol
Sorting relies on a structure like this to describe what is being sorted and in what order:
const sortingColumns = 0: direction: 'asc' position: 1 1: direction: 'desc' position: 0 ;
It maps column index to sorting state and can contain multiple sorters.
Customizing Sorting Order
It is possible to customize the sorting order of sort.byColumn
and sort.byColumns
by passing an object describing the sorting. It should contain FIRST
key to describe the starting point. The remaining key-value pairs should form a cycle.
Assuming you are using the sort
transform, the order values are used for generating the classes you see at the user interface.
The default order cycles between asc
, desc
, and ''
(no sort).
You could implement a custom order cycling between asc
and desc
like this:
const sortingOrder = FIRST: 'asc' asc: 'desc' desc: 'asc';
sort
Transform
The The sort
transform has been designed to track when the user requests sorting and render possibly matching sorting condition as a class for styling. In addition you will need to use specific sort helpers to handle the sorting logic. The helpers have been encapsulated within the sort
module.
Example:
...; ... const sortable = sort; ... // Mark a header as sortablecolumns: property: 'name' header: label: 'name' transforms: sortable
How to Use?
The general workflow goes as follows:
- Set up the
sort
transform. Its purpose is to track when the user requests sorting and render possibly matching sorting condition as a class for styling. - Set up a sort helper. There are helpers for sorting per one column (
sort.byColumn
) and one for sorting per multiple columns (sort.byColumns
). The helpers handle managing sorting conditions and actual sorting. If you have a back-end, you can skip the latter. - Sort the rows before rendering.
- Feed the sorted rows to a
Table
.
You can find suggested default styling for the package at
style.css
in the package root.
Example:
/*import React from 'react';import orderBy from 'lodash/orderBy';import * as resolve from 'table-resolver';import * as Table from 'reactabular-table';import * as sort from 'sortabular';import { compose } from 'redux';*/ const initialRows = id: 100 name: first: 'Adam' last: 'West' age: 10 id: 101 name: first: 'Brian' last: 'Eno' age: 43 id: 102 name: first: 'Brian' last: 'Wilson' age: 23 id: 103 name: first: 'Jake' last: 'Dalton' age: 33 id: 104 name: first: 'Jill' last: 'Jackson' age: 63 ; Component { ; const getSortingColumns = thisstatesortingColumns || ; const sortable = sort; const resetable = sort; thisstate = // Sort the first column in a descending way by default. // "asc" would work too and you can set multiple if you want. sortingColumns: 'name.first': direction: 'desc' position: 0 columns: header: label: 'Name' children: property: 'name.first' header: label: 'First Name' transforms: resetable formatters: sort property: 'name.last' header: label: 'Last Name' transforms: resetable formatters: sort property: 'age' header: label: 'Age' transforms: resetable formatters: sort // Alternative if you don't need reset. // transforms: [sortable] rows: initialRows ; } { const rows sortingColumns columns = thisstate; const resolvedColumns = resolve; const sortedRows = rows; return <div> <Table.Provider => <Table.Header = /> <Table.Body = ="id" /> </Table.Provider> </div> ; } <SortTable />
License
MIT. See LICENSE for details.