Skip to content

Commit b2f632f

Browse files
authored
feat(VDataTable): add initial-sort-order prop (#22156)
resolves #11117 closes #20615
1 parent 54bbc84 commit b2f632f

File tree

8 files changed

+40
-20
lines changed

8 files changed

+40
-20
lines changed

packages/api-generator/src/locale/en/DataTable-sort.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"props": {
33
"customKeySort": "Function used on specific keys within the item object. `customSort` is skipped for columns with `customKeySort` specified.",
44
"disableSort": "Toggles rendering of sort button.",
5+
"initialSortOrder": "Specifies the initial sort order when an unsorted column is clicked.",
56
"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**",
67
"mustSort": "Forces sorting on the column(s).",
78
"sortBy": "Array of column keys and sort orders that determines the sort order of the table."

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"footerProps": "See the [`v-data-footer`](/api/v-data-footer) API for more information.",
99
"groupBy": "Configures attributes (and sort order) to group items together.",
1010
"hideDefaultFooter": "Hides default footer.",
11+
"initialSortOrder": "Specifies the initial sort order when an **toggleSort** is called for unsorted property.",
1112
"itemKey": "The property on each item that is used as a unique key.",
1213
"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.",
1314
"loading": "If `true` and no items are provided, then a loading text will be shown.",

packages/docs/src/data/new-in.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,19 @@
7979
"hideTitle": "3.10.0"
8080
}
8181
},
82+
"VDataIterator": {
83+
"props": {
84+
"initialSortOrder": "3.11.0"
85+
}
86+
},
8287
"VDataTable": {
8388
"props": {
8489
"collapseIcon": "3.10.0",
8590
"expandIcon": "3.10.0",
8691
"groupCollapseIcon": "3.10.0",
8792
"groupExpandIcon": "3.10.0",
88-
"headerProps": "3.5.0"
93+
"headerProps": "3.5.0",
94+
"initialSortOrder": "3.11.0"
8995
},
9096
"slots": {
9197
"group-summary": "3.10.0"
@@ -96,7 +102,8 @@
96102
"collapseIcon": "3.10.0",
97103
"expandIcon": "3.10.0",
98104
"groupCollapseIcon": "3.10.0",
99-
"groupExpandIcon": "3.10.0"
105+
"groupExpandIcon": "3.10.0",
106+
"initialSortOrder": "3.11.0"
100107
},
101108
"slots": {
102109
"group-summary": "3.10.0"
@@ -107,7 +114,8 @@
107114
"collapseIcon": "3.10.0",
108115
"expandIcon": "3.10.0",
109116
"groupCollapseIcon": "3.10.0",
110-
"groupExpandIcon": "3.10.0"
117+
"groupExpandIcon": "3.10.0",
118+
"initialSortOrder": "3.11.0"
111119
},
112120
"slots": {
113121
"group-summary": "3.10.0"

packages/vuetify/src/components/VDataIterator/VDataIterator.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ export const VDataIterator = genericComponent<new <T> (
113113
const { items } = useDataIteratorItems(props)
114114
const { filteredItems } = useFilter(props, items, search, { transform: item => item.raw })
115115

116-
const { sortBy, multiSort, mustSort } = createSort(props)
116+
const { initialSortOrder, sortBy, multiSort, mustSort } = createSort(props)
117117
const { page, itemsPerPage } = createPagination(props)
118118

119-
const { toggleSort } = provideSort({ sortBy, multiSort, mustSort, page })
119+
const { toggleSort } = provideSort({ initialSortOrder, sortBy, multiSort, mustSort, page })
120120
const { sortByWithGroups, opened, extractRows, isGroupOpen, toggleGroup } = provideGroupBy({ groupBy, sortBy })
121121

122122
const { sortedItems } = useSortedItems(props, filteredItems, sortByWithGroups, { transform: item => item.raw })

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const VDataTable = genericComponent<new <T extends readonly any[], V>(
128128

129129
setup (props, { attrs, slots }) {
130130
const { groupBy } = createGroupBy(props)
131-
const { sortBy, multiSort, mustSort } = createSort(props)
131+
const { initialSortOrder, sortBy, multiSort, mustSort } = createSort(props)
132132
const { page, itemsPerPage } = createPagination(props)
133133
const { disableSort } = toRefs(props)
134134

@@ -152,7 +152,7 @@ export const VDataTable = genericComponent<new <T extends readonly any[], V>(
152152
customKeyFilter: filterFunctions,
153153
})
154154

155-
const { toggleSort } = provideSort({ sortBy, multiSort, mustSort, page })
155+
const { toggleSort } = provideSort({ initialSortOrder, sortBy, multiSort, mustSort, page })
156156
const { sortByWithGroups, opened, extractRows, isGroupOpen, toggleGroup } = provideGroupBy({ groupBy, sortBy, disableSort })
157157

158158
const { sortedItems } = useSortedItems(props, filteredItems, sortByWithGroups, {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export const VDataTableServer = genericComponent<new <T extends readonly any[],
6969

7070
setup (props, { attrs, slots }) {
7171
const { groupBy } = createGroupBy(props)
72-
const { sortBy, multiSort, mustSort } = createSort(props)
72+
const { initialSortOrder, sortBy, multiSort, mustSort } = createSort(props)
7373
const { page, itemsPerPage } = createPagination(props)
7474
const { disableSort } = toRefs(props)
7575
const itemsLength = computed(() => parseInt(props.itemsLength, 10))
@@ -82,7 +82,7 @@ export const VDataTableServer = genericComponent<new <T extends readonly any[],
8282

8383
const { items } = useDataTableItems(props, columns)
8484

85-
const { toggleSort } = provideSort({ sortBy, multiSort, mustSort, page })
85+
const { toggleSort } = provideSort({ initialSortOrder, sortBy, multiSort, mustSort, page })
8686

8787
const { opened, isGroupOpen, toggleGroup, extractRows } = provideGroupBy({ groupBy, sortBy, disableSort })
8888

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const VDataTableVirtual = genericComponent<new <T extends readonly any[],
8989

9090
setup (props, { attrs, slots }) {
9191
const { groupBy } = createGroupBy(props)
92-
const { sortBy, multiSort, mustSort } = createSort(props)
92+
const { initialSortOrder, sortBy, multiSort, mustSort } = createSort(props)
9393
const { disableSort } = toRefs(props)
9494

9595
const {
@@ -111,7 +111,7 @@ export const VDataTableVirtual = genericComponent<new <T extends readonly any[],
111111
customKeyFilter: filterFunctions,
112112
})
113113

114-
const { toggleSort } = provideSort({ sortBy, multiSort, mustSort })
114+
const { toggleSort } = provideSort({ initialSortOrder, sortBy, multiSort, mustSort })
115115
const { sortByWithGroups, opened, extractRows, isGroupOpen, toggleGroup } = provideGroupBy({ groupBy, sortBy, disableSort })
116116

117117
const { sortedItems } = useSortedItems(props, filteredItems, sortByWithGroups, {

packages/vuetify/src/components/VDataTable/composables/sort.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import type { DataTableCompareFunction, InternalDataTableHeader } from '../types
1212
import type { InternalItem } from '@/composables/filter'
1313

1414
export const makeDataTableSortProps = propsFactory({
15+
initialSortOrder: {
16+
type: String as PropType<'asc' | 'desc'>,
17+
default: 'asc',
18+
validator: (v: any) => !v || ['asc', 'desc'].includes(v),
19+
},
1520
sortBy: {
1621
type: Array as PropType<readonly SortItem[]>,
1722
default: () => ([]),
@@ -40,17 +45,19 @@ export type MultiSortProps = {
4045
export type MultiSortMode = 'append' | 'prepend'
4146

4247
type SortProps = {
48+
initialSortOrder: 'asc' | 'desc'
4349
sortBy: readonly SortItem[]
4450
'onUpdate:sortBy': ((value: any) => void) | undefined
4551
multiSort: boolean | MultiSortProps
4652
mustSort: boolean
4753
}
4854

4955
export function createSort (props: SortProps) {
56+
const initialSortOrder = toRef(() => props.initialSortOrder)
5057
const sortBy = useProxiedModel(props, 'sortBy')
5158
const mustSort = toRef(() => props.mustSort)
5259
const multiSort = toRef(() => props.multiSort)
53-
return { sortBy, mustSort, multiSort }
60+
return { initialSortOrder, sortBy, multiSort, mustSort }
5461
}
5562

5663
function resolveMultiSort (
@@ -75,38 +82,41 @@ function resolveMultiSort (
7582
}
7683

7784
export function provideSort (options: {
85+
initialSortOrder: Ref<'asc' | 'desc'>
7886
sortBy: Ref<readonly SortItem[]>
79-
mustSort: Ref<boolean>
8087
multiSort: Ref<boolean | MultiSortProps>
88+
mustSort: Ref<boolean>
8189
page?: Ref<number>
8290
}) {
83-
const { sortBy, mustSort, multiSort, page } = options
91+
const { initialSortOrder, sortBy, mustSort, multiSort, page } = options
8492

8593
const toggleSort = (column: InternalDataTableHeader, event?: KeyboardEvent | PointerEvent) => {
8694
if (column.key == null) return
8795

8896
let newSortBy = sortBy.value.map(x => ({ ...x })) ?? []
8997
const item = newSortBy.find(x => x.key === column.key)
9098

99+
const initialOrder = initialSortOrder.value
100+
const secondaryOrder = initialSortOrder.value === 'desc' ? 'asc' : 'desc'
91101
if (!item) {
92102
const { active, mode } = resolveMultiSort(multiSort.value, event)
93103
if (active) {
94104
if (mode === 'prepend') {
95-
newSortBy.unshift({ key: column.key, order: 'asc' })
105+
newSortBy.unshift({ key: column.key, order: initialOrder })
96106
} else {
97-
newSortBy.push({ key: column.key, order: 'asc' })
107+
newSortBy.push({ key: column.key, order: initialOrder })
98108
}
99109
} else {
100-
newSortBy = [{ key: column.key, order: 'asc' }]
110+
newSortBy = [{ key: column.key, order: initialOrder }]
101111
}
102-
} else if (item.order === 'desc') {
112+
} else if (item.order === secondaryOrder) {
103113
if (mustSort.value && newSortBy.length === 1) {
104-
item.order = 'asc'
114+
item.order = initialSortOrder.value
105115
} else {
106116
newSortBy = newSortBy.filter(x => x.key !== column.key)
107117
}
108118
} else {
109-
item.order = 'desc'
119+
item.order = secondaryOrder
110120
}
111121

112122
sortBy.value = newSortBy

0 commit comments

Comments
 (0)