observablehq / inputs

Better input elements
https://observablehq.com/framework/lib/inputs
ISC License
127 stars 34 forks source link

Stacked sorts on Input.table() #228

Open hellonearthis opened 2 years ago

hellonearthis commented 2 years ago

Having the ability to stack sorts on an Input.table(dates,{sort:'date',sort:'month'}) would be useful.
Dates is an unordered list.

For example. I could sort by date and then month to get put my data into chronological order.
It's like clicking on the dates column and then the months column.

image

I thought that issue 114 was similar but it would not give the same results as a cascading sort.

Fil commented 2 years ago

The syntax would have to be slightly different—maybe with:

mootari commented 2 years ago

Sorting by additional columns would probably require some modifier key. Otherwise the sorts would only continue to stack up, with no apparent way to set a new primary sort column.

A few other things to consider:

lionel-rowe commented 10 months ago

A possible API could look something like this:

const PRIORITIES = ['low', 'medium', 'high']

const data = [
    { title: 'b', chinese: '安', date: new Date('2023-12-01T00:00:00Z'), priority: 'medium' },
    { title: 'a', chinese: '测', date: new Date('2023-12-05T00:00:00Z'), priority: 'low' },
    { title: 'c', chinese: '比', date: new Date('2023-12-02T00:00:00Z'), priority: 'high' },
]

Inputs.table(data, {
    columns: ['title', 'chinese', 'date', 'priority'],
    sort: [
        // needs to be an array not an obj at top level because ordering is important
        // (i.e. if result of first comparator is non-zero, other comparators aren't evaluated)
        { column: 'priority', direction: 'desc' },
        { column: 'date', direction: 'asc' },
    ],
    comparators: {
        title: new Intl.Collator('en-US').compare,
        chinese: new Intl.Collator('zh-CN').compare,
        date: (a, b) => d3.ascending(a.date, b.date),
        priority: (a, b) => PRIORITIES.indexOf(a.priority) - PRIORITIES.indexOf(b.priority),
    },
})

In this example, the default sorting would be by priority (from high to low), and within the same priority, by date (from earlier to later).

User interaction for nuking the stacked sort order and setting a new "simple" sort order (i.e. based on a single column using its comparator, or default generic comparator if none set) would be the same as the current one, i.e. clicking that column heading, alternating between asc and desc orderings. Regarding users setting their own stacked sort orders, I'm not sure, but at a minimum it'd be nice to have a user action for "reset to default sort order" (whether simple, stacked, or completely unsorted).