diff --git a/docs/components/table-data.md b/docs/components/table-data.md index 3cb0c2d936..a56eec1fa1 100644 --- a/docs/components/table-data.md +++ b/docs/components/table-data.md @@ -38,6 +38,8 @@ interface TableDataHeader { label: string /** this property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */ sortable?: boolean + /** When provided, determines the intial arrow direction on the column header, if more than one header has this value only the first is applied */ + initialSort?: 'asc' | 'desc' /** allow toggling column visibility */ hidable?: boolean /** when provided, an info icon will be rendered next to the column label, upon hovering on which the tooltip will be revealed */ diff --git a/docs/components/table-view.md b/docs/components/table-view.md index 451ce004c8..55cddba9fb 100644 --- a/docs/components/table-view.md +++ b/docs/components/table-view.md @@ -34,6 +34,8 @@ interface TableViewHeader { label: string /** this property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */ sortable?: boolean + /** When provided, determines the intial arrow direction on the column header, if more than one header has this value only the first is applied */ + initialSort?: 'asc' | 'desc' /** allow toggling column visibility */ hidable?: boolean /** when provided, an info icon will be rendered next to the column label, upon hovering on which the tooltip will be revealed */ diff --git a/sandbox/pages/SandboxTableData.vue b/sandbox/pages/SandboxTableData.vue index df11cf9580..1b37cc1ac1 100644 --- a/sandbox/pages/SandboxTableData.vue +++ b/sandbox/pages/SandboxTableData.vue @@ -12,7 +12,7 @@
+ +
@@ -31,7 +43,10 @@ :key="data.tableKey" client-sort :fetcher="fetcher" - :headers="headers(false, true)" + :headers="headers(false, data.usernameSortable, false, data.initialSort)" + :initial-fetcher-params="data.tableSortable && data.usernameSortable && data.initialSort + ? { sortColumnKey: 'username', sortColumnOrder: 'asc' } + : {}" max-height="300" :row-hover="data.tableRowHover" :sort-handler-function="sortHandlerFunction" @@ -49,7 +64,7 @@ >
{ +const headers = ( + hidable: boolean = false, + sortable: boolean = false, + bulkActions: boolean = false, + hasInitialSort: boolean = false, +): TableDataHeader[] => { return [ { key: 'actions', label: 'Row actions' }, - { key: 'name', label: 'Full Name' }, + { + key: 'name', + label: 'Full Name', + sortable: true, + useSortHandlerFunction: true, + }, { key: 'username', label: 'Username', tooltip: 'Columns with a tooltip.', sortable, ...(sortable && { useSortHandlerFunction: true }), + ...(hasInitialSort && { initialSort: 'asc' }), }, { key: 'email', label: 'Email', hidable }, ...(bulkActions ? [{ key: 'bulkActions', label: 'Bulk actions' }] : []), ] } -const fetcher = async (): Promise => { +const fetcher = async ({ sortColumnKey, sortColumnOrder }): Promise => { // Fake delay await new Promise((resolve) => setTimeout(resolve, 2000)) const response = await fetch('https://jsonplaceholder.typicode.com/users') const responseData = await response.json() - return { - data: responseData, - total: responseData.length, - } + return sortColumnKey + ? { + data: sortHandlerFunction({ key: sortColumnKey, sortColumnOrder, data: responseData }), + total: responseData.length, + } + : { + data: responseData, + total: responseData.length, + } } const emptyFetcher = async (): Promise => { @@ -478,29 +509,11 @@ const emptyFetcher = async (): Promise => { } const sortHandlerFunction = ({ key, sortColumnOrder, data }: any) => { - return data.sort((a: any, b: any) => { - if (key === 'username') { - if (sortColumnOrder === 'asc') { - if (a.username > b.username) { - return 1 - } else if (a.username < b.username) { - return -1 - } - - return 0 - } else { - if (a.username > b.username) { - return -1 - } else if (a.username < b.username) { - return 1 - } - - return 0 - } - } + const ascending = sortColumnOrder === 'asc' - return data - }) + return data.sort((a: any, b: any) => ascending + ? (a[key] ?? '').localeCompare(b[key] ?? '') + : (b[key] ?? '').localeCompare(a[key] ?? '')) } const onRowClick = (row: any) => { diff --git a/src/components/KTableView/KTableView.vue b/src/components/KTableView/KTableView.vue index 698d00b4cf..5d4dcbbd62 100644 --- a/src/components/KTableView/KTableView.vue +++ b/src/components/KTableView/KTableView.vue @@ -212,12 +212,20 @@ - +
headers, (newVal: readonly Header[]) => { headers.push(actionsHeader) } + const firstInitialSort = newVal.find(({ initialSort }) => initialSort) + if (!sortColumnKey.value && firstInitialSort) { + sortColumnKey.value = firstInitialSort.key + // @ts-ignore - initialSort can't be undefined here because we filtered for it already + sortColumnOrder.value = firstInitialSort.initialSort + } + tableHeaders.value = headers } }, { deep: true, immediate: true }) diff --git a/src/styles/mixins/_tables.scss b/src/styles/mixins/_tables.scss index 77fe18e1d3..ab9756aadc 100644 --- a/src/styles/mixins/_tables.scss +++ b/src/styles/mixins/_tables.scss @@ -161,6 +161,15 @@ &.sortable { cursor: pointer; + .sort-possible-icon { + transform: rotate(90deg); + } + + .sort-icon { + transform: rotate(0deg); + transition: transform $kongponentsTransitionDurTimingFunc; + } + &.asc .sort-icon { transform: rotate(-180deg); } diff --git a/src/types/table.ts b/src/types/table.ts index 442d0c078a..28423fb0ad 100644 --- a/src/types/table.ts +++ b/src/types/table.ts @@ -79,6 +79,8 @@ export interface TableViewHeader { label?: string /** This property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */ sortable?: boolean + /** When provided, determines the intial arrow direction on the column */ + initialSort?: SortColumnOrder /** Allow toggling column visibility */ hidable?: boolean /** When provided, an info icon will be rendered next to the column label, upon hovering on which the tooltip will be revealed */