Skip to content

Commit 54bbc84

Browse files
authored
feat(VDataTable): multi-sort mode and keyboard modifiers (#22133)
resolves #22132
1 parent efa50e4 commit 54bbc84

File tree

14 files changed

+93
-198
lines changed

14 files changed

+93
-198
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"props": {
33
"customKeySort": "Function used on specific keys within the item object. `customSort` is skipped for columns with `customKeySort` specified.",
4+
"disableSort": "Toggles rendering of sort button.",
5+
"multiSort": "Let user sort by multiple properties/columns.\n\n- **key**: (optional) when set to `ctrl`, user is required to hold a keyboard key (Ctrl on PC and Command on Mac)\n- **mode**: when user selects a new column to sort by, it will be set first (`prepend`) or last (`append`) in the sort priority. Defaults to `append`\n- **modifier**: (optional) allows user to use both multi-sort modes (`append` and `prepend`) simultaneously\n\n**Note**: object notation requires at least **v3.11.0**",
46
"mustSort": "Forces sorting on the column(s).",
57
"sortBy": "Array of column keys and sort orders that determines the sort order of the table."
6-
78
}
89
}

packages/api-generator/src/locale/en/VDataIterator.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
"props": {
33
"customFilter": "Function to filter items.",
44
"customGroup": "Function used to group items.",
5-
"customSort": "Function used to sort items.",
65
"disableFiltering": "Disables filtering completely.",
76
"disablePagination": "Disables pagination completely.",
8-
"disableSort": "Disables sorting completely.",
97
"expanded": "Array of expanded items. Can be bound to external variable using **v-model:expanded**.",
108
"footerProps": "See the [`v-data-footer`](/api/v-data-footer) API for more information.",
119
"groupBy": "Configures attributes (and sort order) to group items together.",
@@ -16,15 +14,12 @@
1614
"loadingText": "Text shown when `loading` is true and no items are provided.",
1715
"locale": "Sets the locale used for sorting. This is passed into [`Intl.Collator()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator) in the default `customSort` function.",
1816
"mobileBreakpoint": "Used to set when to toggle between regular table and mobile view.",
19-
"multiSort": "If `true` then one can sort on multiple properties.",
20-
"mustSort": "If `true` then one can not disable sorting, it will always switch between ascending and descending.",
2117
"noResultsText": "Text shown when `search` prop is used and there are no results.",
2218
"search": "Text input used to filter items.",
2319
"selectableKey": "The property on each item that is used to determine if it is selectable or not.",
2420
"serverItemsLength": "Used only when data is provided by a server. Should be set to the total amount of items available on server so that pagination works correctly.",
2521
"singleExpand": "Changes expansion mode to single expand.",
2622
"singleSelect": "Changes selection mode to single select.",
27-
"sortBy": "Changes which item property (or properties) should be used for sort order. Can be bound to external variable using **v-model:sortBy**.",
2823
"value": "Used for controlling selected rows."
2924
},
3025
"slots": {

packages/api-generator/src/locale/en/VDataTable.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"density": "Adjusts the vertical height of the table rows.",
99
"disableFiltering": "Disables filtering completely.",
1010
"disablePagination": "Disables pagination completely.",
11-
"disableSort": "Disables sorting completely.",
1211
"expandIcon": "Icon to display when the expandable row is collapsed.",
1312
"fixedHeader": "Fixed header to top of table.",
1413
"groupBy": "Configures attributes (and sort order) to group items together. Can be customized further with `group-header` and `group-summary` slots.",
@@ -22,8 +21,6 @@
2221
"itemClass": "Property on supplied `items` that contains item's row class or function that takes an item as an argument and returns the class of corresponding row.",
2322
"itemsPerPage": "Changes how many items per page should be visible. Can be bound to external variable using **v-model:itemsPerPage**.. Setting this prop to `-1` will display all items on the page.",
2423
"locale": "Sets the locale used for sorting. This is passed into [`Intl.Collator()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator) in the default `customSort` function.",
25-
"multiSort": "If `true` then one can sort on multiple properties.",
26-
"mustSort": "If `true` then one can not disable sorting, it will always switch between ascending and descending.",
2724
"page": "The current displayed page number (1-indexed).",
2825
"serverItemsLength": "Used only when data is provided by a server. Should be set to the total amount of items available on server so that pagination works correctly.",
2926
"showSelect": "Shows the select checkboxes in both the header and rows (if using default rows).",

packages/api-generator/src/locale/en/VDataTableHeaders.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
{
22
"props": {
33
"color": "Applies a color to sort badges in the table header.",
4-
"disableSort": "Toggles rendering of sort button.",
54
"sortAscIcon": "Icon used for ascending sort button.",
65
"sortDescIcon": "Icon used for descending sort button.",
76
"sticky": "Deprecated, use `fixed-header` instead.",
87
"fixedHeader": "Sticks the header to the top of the table.",
98
"lastFixed": "**FOR INTERNAL USE ONLY** Applies right border to the last column fixed to the left.",
109
"firstFixedEnd": "**FOR INTERNAL USE ONLY** Applies left border to the first column fixed to the right.",
11-
"multiSort": "Sort on multiple columns at the same time.",
1210
"headerProps": "Additional props to be be passed to the default header"
1311
},
1412
"slots": {

packages/api-generator/src/locale/en/VDataTableRows.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"cellProps": "An object of additional props to be passed to each `<td>` in the table body. Also accepts a function that will be called for each cell. If the same prop is defined both here and in `cellProps` in a headers object, the value from the headers object will be used.",
44
"loading": "Displays `loading` slot if set to `true`",
55
"loadingText": "Text shown when the data is loading.",
6-
"multiSort": "Allows sorting by multiple columns.",
76
"rowProps": "An object of additional props to be passed to each `<tr>` in the table body. Also accepts a function that will be called for each row."
87
},
98
"events": {

packages/api-generator/src/locale/en/VDataTableServer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"column.data-table-select": "Slot to replace the default `v-checkbox-btn` used when selecting rows.",
1919
"dataTableGroup": "Slot for custom rendering of a group.",
2020
"data-table-select": "Slot for custom rendering of a header cell with the select checkbox.",
21-
"disableSort": "Disables sorting completely.",
2221
"expanded-row": "Slot for custom rendering of an expanded row.",
2322
"footer.prepend": "Adds content to the empty space in the footer.",
2423
"group-header": "Slot for custom rendering of a group header.",

packages/api-generator/src/locale/en/VDataTableVirtual.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"column.data-table-select": "Slot to replace the default `v-checkbox-btn` used when selecting rows.",
1919
"data-table-group": "Slot for custom rendering of a group.",
2020
"data-table-select": "Slot for custom rendering of a header cell with the select checkbox.",
21-
"disableSort": "Disables sorting completely.",
2221
"expanded-row": "Slot for custom rendering of an expanded row.",
2322
"group-header": "Slot for custom rendering of a group header.",
2423
"group-summary": "Slot for custom rendering of a group summary.",

packages/docs/src/examples/v-data-table/prop-multi-sort.vue

Lines changed: 31 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
<template>
2-
<v-data-table
3-
:headers="headers"
4-
:items="desserts"
5-
:sort-by="[{ key: 'calories', order: 'asc' }, { key: 'fat', order: 'desc' }]"
6-
multi-sort
7-
></v-data-table>
2+
<div>
3+
<v-alert class="mb-2" density="compact" variant="outlined">
4+
<strong>Hint:</strong> Hold <v-kbd>Alt</v-kbd> to prepend new columns to <v-code>sort-by</v-code> array
5+
</v-alert>
6+
<v-data-table
7+
:headers="headers"
8+
:items="desserts"
9+
:multi-sort="{ mode: 'append', modifier: 'alt' }"
10+
:sort-by="[{ key: 'calories', order: 'asc' }, { key: 'fat', order: 'desc' }]"
11+
></v-data-table>
12+
</div>
813
</template>
914

1015
<script setup>
@@ -22,86 +27,16 @@
2227
{ title: 'Iron (%)', key: 'iron' },
2328
]
2429
const desserts = [
25-
{
26-
name: 'Frozen Yogurt',
27-
calories: 200,
28-
fat: 6,
29-
carbs: 24,
30-
protein: 4,
31-
iron: 1,
32-
},
33-
{
34-
name: 'Ice cream sandwich',
35-
calories: 200,
36-
fat: 9,
37-
carbs: 37,
38-
protein: 4.3,
39-
iron: 1,
40-
},
41-
{
42-
name: 'Eclair',
43-
calories: 300,
44-
fat: 16,
45-
carbs: 23,
46-
protein: 6,
47-
iron: 7,
48-
},
49-
{
50-
name: 'Cupcake',
51-
calories: 300,
52-
fat: 3.7,
53-
carbs: 67,
54-
protein: 4.3,
55-
iron: 8,
56-
},
57-
{
58-
name: 'Gingerbread',
59-
calories: 400,
60-
fat: 16,
61-
carbs: 49,
62-
protein: 3.9,
63-
iron: 16,
64-
},
65-
{
66-
name: 'Jelly bean',
67-
calories: 400,
68-
fat: 0,
69-
carbs: 94,
70-
protein: 0,
71-
iron: 0,
72-
},
73-
{
74-
name: 'Lollipop',
75-
calories: 400,
76-
fat: 0.2,
77-
carbs: 98,
78-
protein: 0,
79-
iron: 2,
80-
},
81-
{
82-
name: 'Honeycomb',
83-
calories: 400,
84-
fat: 3.2,
85-
carbs: 87,
86-
protein: 6.5,
87-
iron: 45,
88-
},
89-
{
90-
name: 'Donut',
91-
calories: 500,
92-
fat: 25,
93-
carbs: 51,
94-
protein: 4.9,
95-
iron: 22,
96-
},
97-
{
98-
name: 'KitKat',
99-
calories: 500,
100-
fat: 26,
101-
carbs: 65,
102-
protein: 7,
103-
iron: 6,
104-
},
30+
{ name: 'Frozen Yogurt', calories: 200, fat: 6, carbs: 24, protein: 4, iron: 1 },
31+
{ name: 'Ice cream sandwich', calories: 200, fat: 9, carbs: 37, protein: 4.3, iron: 1 },
32+
{ name: 'Eclair', calories: 300, fat: 16, carbs: 23, protein: 6, iron: 7 },
33+
{ name: 'Cupcake', calories: 300, fat: 3.7, carbs: 67, protein: 4.3, iron: 8 },
34+
{ name: 'Gingerbread', calories: 400, fat: 16, carbs: 49, protein: 3.9, iron: 16 },
35+
{ name: 'Jelly bean', calories: 400, fat: 0, carbs: 94, protein: 0, iron: 0 },
36+
{ name: 'Lollipop', calories: 400, fat: 0.2, carbs: 98, protein: 0, iron: 2 },
37+
{ name: 'Honeycomb', calories: 400, fat: 3.2, carbs: 87, protein: 6.5, iron: 45 },
38+
{ name: 'Donut', calories: 500, fat: 25, carbs: 51, protein: 4.9, iron: 22 },
39+
{ name: 'KitKat', calories: 500, fat: 26, carbs: 65, protein: 7, iron: 6 },
10540
]
10641
</script>
10742

@@ -123,86 +58,16 @@
12358
{ title: 'Iron (%)', key: 'iron' },
12459
],
12560
desserts: [
126-
{
127-
name: 'Frozen Yogurt',
128-
calories: 200,
129-
fat: 6.0,
130-
carbs: 24,
131-
protein: 4.0,
132-
iron: 1,
133-
},
134-
{
135-
name: 'Ice cream sandwich',
136-
calories: 200,
137-
fat: 9.0,
138-
carbs: 37,
139-
protein: 4.3,
140-
iron: 1,
141-
},
142-
{
143-
name: 'Eclair',
144-
calories: 300,
145-
fat: 16.0,
146-
carbs: 23,
147-
protein: 6.0,
148-
iron: 7,
149-
},
150-
{
151-
name: 'Cupcake',
152-
calories: 300,
153-
fat: 3.7,
154-
carbs: 67,
155-
protein: 4.3,
156-
iron: 8,
157-
},
158-
{
159-
name: 'Gingerbread',
160-
calories: 400,
161-
fat: 16.0,
162-
carbs: 49,
163-
protein: 3.9,
164-
iron: 16,
165-
},
166-
{
167-
name: 'Jelly bean',
168-
calories: 400,
169-
fat: 0.0,
170-
carbs: 94,
171-
protein: 0.0,
172-
iron: 0,
173-
},
174-
{
175-
name: 'Lollipop',
176-
calories: 400,
177-
fat: 0.2,
178-
carbs: 98,
179-
protein: 0,
180-
iron: 2,
181-
},
182-
{
183-
name: 'Honeycomb',
184-
calories: 400,
185-
fat: 3.2,
186-
carbs: 87,
187-
protein: 6.5,
188-
iron: 45,
189-
},
190-
{
191-
name: 'Donut',
192-
calories: 500,
193-
fat: 25.0,
194-
carbs: 51,
195-
protein: 4.9,
196-
iron: 22,
197-
},
198-
{
199-
name: 'KitKat',
200-
calories: 500,
201-
fat: 26.0,
202-
carbs: 65,
203-
protein: 7,
204-
iron: 6,
205-
},
61+
{ name: 'Frozen Yogurt', calories: 200, fat: 6.0, carbs: 24, protein: 4.0, iron: 1 },
62+
{ name: 'Ice cream sandwich', calories: 200, fat: 9.0, carbs: 37, protein: 4.3, iron: 1 },
63+
{ name: 'Eclair', calories: 300, fat: 16.0, carbs: 23, protein: 6.0, iron: 7 },
64+
{ name: 'Cupcake', calories: 300, fat: 3.7, carbs: 67, protein: 4.3, iron: 8 },
65+
{ name: 'Gingerbread', calories: 400, fat: 16.0, carbs: 49, protein: 3.9, iron: 16 },
66+
{ name: 'Jelly bean', calories: 400, fat: 0.0, carbs: 94, protein: 0.0, iron: 0 },
67+
{ name: 'Lollipop', calories: 400, fat: 0.2, carbs: 98, protein: 0, iron: 2 },
68+
{ name: 'Honeycomb', calories: 400, fat: 3.2, carbs: 87, protein: 6.5, iron: 45 },
69+
{ name: 'Donut', calories: 500, fat: 25.0, carbs: 51, protein: 4.9, iron: 22 },
70+
{ name: 'KitKat', calories: 500, fat: 26.0, carbs: 65, protein: 7, iron: 6 },
20671
],
20772
}
20873
},

packages/docs/src/pages/en/components/data-tables/data-and-display.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ Unless you are using the **multi-sort** prop seen below, this array will almost
122122

123123
### Multi sort
124124

125-
Using the **multi-sort** prop will enable you to sort on multiple columns at the same time.
125+
Using the **multi-sort** prop will allow user to sort on multiple columns at the same time. You can specify whether new columns should be added first or last to the **sort-by** array. By specifying optional **modifier** key, you can support both modes.
126+
127+
::: warning
128+
`multi-sort` with object parameter requires at least [v3.11.0](/getting-started/release-notes/?version=v3.11.0)
129+
:::
126130

127131
<ExamplesExample file="v-data-table/prop-multi-sort" />
128132

packages/vuetify/src/components/VDataTable/VDataTable.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { makeFilterProps, useFilter } from '@/composables/filter'
2222

2323
// Utilities
2424
import { computed, toRef, toRefs } from 'vue'
25-
import { genericComponent, propsFactory, useRender } from '@/util'
25+
import { genericComponent, omit, propsFactory, useRender } from '@/util'
2626

2727
// Types
2828
import type { DeepReadonly, UnwrapRef } from 'vue'
@@ -85,7 +85,7 @@ export const makeDataTableProps = propsFactory({
8585
...makeDataTableItemsProps(),
8686
...makeDataTableSelectProps(),
8787
...makeDataTableSortProps(),
88-
...makeVDataTableHeadersProps(),
88+
...omit(makeVDataTableHeadersProps(), ['multiSort']),
8989
...makeVTableProps(),
9090
}, 'DataTable')
9191

@@ -222,7 +222,7 @@ export const VDataTable = genericComponent<new <T extends readonly any[], V>(
222222

223223
useRender(() => {
224224
const dataTableFooterProps = VDataTableFooter.filterProps(props)
225-
const dataTableHeadersProps = VDataTableHeaders.filterProps(props)
225+
const dataTableHeadersProps = VDataTableHeaders.filterProps(omit(props, ['multiSort']))
226226
const dataTableRowsProps = VDataTableRows.filterProps(props)
227227
const tableProps = VTable.filterProps(props)
228228

@@ -249,6 +249,7 @@ export const VDataTable = genericComponent<new <T extends readonly any[], V>(
249249
<thead key="thead">
250250
<VDataTableHeaders
251251
{ ...dataTableHeadersProps }
252+
multiSort={ !!props.multiSort }
252253
v-slots={ slots }
253254
/>
254255
</thead>

0 commit comments

Comments
 (0)