Skip to content

Commit

Permalink
feat(table): expose sort function (#959)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlmoravek authored Jun 14, 2024
1 parent e89b761 commit e9030bd
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 52 deletions.
2 changes: 1 addition & 1 deletion packages/docs/components/Table.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ sidebarDepth: 2
| customDetailRow | Enable custom style on details (if detailed) | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| data | Table data | T[] | - | Default function (see source code) |
| debounceSearch | Filtering debounce time (in milliseconds) | number | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;debounceSearch: undefined<br>}</code> |
| defaultSort | Sets the default sort column and order — e.g. ['first_name', 'desc'] | string \| string[] | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;defaultSort: undefined<br>}</code> |
| defaultSort | Sets the default sort column and order — e.g. 'first_name' or ['first_name', 'desc'] | string \| [string, "asc" \| "desc"] | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;defaultSort: undefined<br>}</code> |
| defaultSortDirection | Sets the default sort column direction on the first click | string | `asc`, `desc` | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;defaultSortDirection: "asc"<br>}</code> |
| detailIcon | Icon name of detail action (if detailed) | string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;detailIcon: "chevron-right"<br>}</code> |
| detailTransition | | string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;detailTransition: "slide"<br>}</code> |
Expand Down
77 changes: 39 additions & 38 deletions packages/oruga/src/components/table/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ import type {
} from "./types";
import type { ComponentClass, ClassBind, OrugaOptions } from "@/types";
enum SortDirection {
ASC = "asc",
DESC = "desc",
}
/**
* Tabulated data are sometimes needed, it's even better when it's responsive
* @displayName Table
Expand Down Expand Up @@ -193,17 +198,18 @@ const props = defineProps({
type: Boolean,
default: () => getOption("table.backendSorting", false),
},
/** Sets the default sort column and order — e.g. ['first_name', 'desc'] */
/** Sets the default sort column and order — e.g. 'first_name' or ['first_name', 'desc'] */
defaultSort: {
type: [String, Array] as PropType<string | string[]>,
type: [String, Array] as PropType<string | [string, "asc" | "desc"]>,
default: () => getOption("table.defaultSort"),
},
/**
* Sets the default sort column direction on the first click
* @values asc, desc
*/
defaultSortDirection: {
type: String,
type: String as PropType<"asc" | "desc">,
validator: (value: string) => ["asc", "desc"].indexOf(value) >= 0,
default: () => getOption("table.defaultSortDirection", "asc"),
},
/** Sets the header sorting icon */
Expand Down Expand Up @@ -1070,8 +1076,6 @@ function filterRows(rows: TableRow<T>[]): TableRow<T>[] {
const currentSortColumn = ref<TableColumnItem<T>>();
const isAsc = ref(true);
onMounted(() => nextTick(() => checkSort()));
/** check if has any sortable column */
const hasSortableColumns = computed(() =>
tableColumns.value.some((column) => column.sortable),
Expand All @@ -1082,44 +1086,23 @@ function isColumnSorted(column: TableColumnItem<T>): boolean {
return currentSortColumn.value?.identifier === column.identifier;
}
/** call initSort only first time (For example async data) */
function checkSort(): void {
if (tableColumns.value.length && !currentSortColumn.value) {
// is first time sort
initSort();
} else if (tableColumns.value.length) {
if (
currentSortColumn.value &&
Object.keys(currentSortColumn.value).length > 0
) {
const column = tableColumns.value.find(
(column) => currentSortColumn.value.field === column.field,
);
if (column) currentSortColumn.value = column;
}
}
}
// call initSort only first time (for example async data)
// initSort must be called after TableColumns got initialised first time
onMounted(() => nextTick(() => initSort()));
/** initial sorted column based on the default-sort prop */
function initSort(): void {
if (!tableColumns.value.length || currentSortColumn.value) return;
if (!props.defaultSort) return;
let sortField = "";
let sortDirection = props.defaultSortDirection;
if (Array.isArray(props.defaultSort)) {
sortField = props.defaultSort[0];
if (props.defaultSort[1]) {
sortDirection = props.defaultSort[1];
}
if (props.defaultSort[1]) sortDirection = props.defaultSort[1];
} else {
sortField = props.defaultSort;
}
const sortColumn = tableColumns.value.find(
(column) => column.field === sortField,
);
if (sortColumn) {
isAsc.value = sortDirection.toLowerCase() !== "desc";
sort(sortColumn, true);
}
sortByField(sortField, sortDirection as SortDirection);
}
/**
Expand All @@ -1134,20 +1117,38 @@ function sort(
): void {
if (!column || !column.sortable) return;
if (!updateDirection)
if (updateDirection)
isAsc.value = isColumnSorted(column)
? !isAsc.value
: props.defaultSortDirection.toLowerCase() !== "desc";
: props.defaultSortDirection.toLowerCase() === SortDirection.ASC;
// if not first time sort
if (currentSortColumn.value)
emits("sort", column, isAsc.value ? "asc" : "desc", event);
emits(
"sort",
column,
isAsc.value ? SortDirection.ASC : SortDirection.DESC,
event,
);
currentSortColumn.value = column;
// recompute rows with updated currentSortColumn
processTableData();
}
function sortByField(
field: string,
direction: SortDirection = SortDirection.ASC,
): void {
const sortColumn = tableColumns.value.find(
(column) => column.field === field,
);
if (sortColumn) {
isAsc.value = direction.toLowerCase() === SortDirection.ASC;
sort(sortColumn);
}
}
function sortByColumn(rows: TableRow<T>[]): TableRow<T>[] {
const column = currentSortColumn.value;
if (!column) return rows;
Expand Down Expand Up @@ -1559,7 +1560,7 @@ function tdClasses(row: TableRow<T>, column: TableColumnItem<T>): ClassBind[] {
// --- Expose Public Functionalities ---
/** expose functionalities for programmatic usage */
defineExpose({ rows: tableData });
defineExpose({ rows: tableData, sort: sortByField });
</script>

<template>
Expand Down Expand Up @@ -1601,7 +1602,7 @@ defineExpose({ rows: tableData });
:sort-icon-size="sortIconSize"
:is-asc="isAsc"
:mobile-sort-classes="mobileSortClasses"
@sort="(column, event) => sort(column, null, event)" />
@sort="(column, event) => sort(column, true, event)" />

<template
v-if="
Expand Down Expand Up @@ -1701,7 +1702,7 @@ defineExpose({ rows: tableData });
:class="thClasses(column)"
:style="isMobileActive ? {} : column.style"
:draggable="canDragColumn"
@click.stop="sort(column, null, $event)"
@click.stop="sort(column, true, $event)"
@dragstart="
handleColumnDragStart(column, index, $event)
"
Expand Down
4 changes: 1 addition & 3 deletions packages/oruga/src/components/table/examples/async-data.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const data = ref([]);
const total = ref(0);
const loading = ref(false);
const sortField = ref("vote_count");
const sortOrder = ref("desc");
const defaultSortOrder = ref("desc");
const sortOrder = ref<"asc" | "desc">("desc");
const page = ref(1);
const perPage = ref(20);
Expand Down Expand Up @@ -93,7 +92,6 @@ onMounted(() => {
:total="total"
:per-page="perPage"
backend-sorting
:default-sort-direction="defaultSortOrder"
:default-sort="[sortField, sortOrder]"
aria-next-label="Next page"
aria-previous-label="Previous page"
Expand Down
14 changes: 9 additions & 5 deletions packages/oruga/src/components/table/examples/customise.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,33 +82,37 @@ const hasMobileCards = ref(true);
field="id"
label="ID"
width="40"
numeric>
numeric
sortable>
{{ row.id }}
</o-table-column>

<o-table-column
v-slot="{ row }"
field="first_name"
label="First Name">
label="First Name"
sortable>
{{ row.first_name }}
</o-table-column>

<o-table-column
v-slot="{ row }"
field="last_name"
label="Last Name">
label="Last Name"
sortable>
{{ row.last_name }}
</o-table-column>

<o-table-column
v-slot="{ row }"
field="date"
label="Date"
position="centered">
position="centered"
sortable>
{{ new Date(row.date).toLocaleDateString() }}
</o-table-column>

<o-table-column v-slot="{ row }" label="Gender">
<o-table-column v-slot="{ row }" label="Gender" sortable>
<o-icon
pack="fas"
:icon="row.gender === 'Male' ? 'mars' : 'venus'" />
Expand Down
1 change: 0 additions & 1 deletion packages/oruga/src/components/table/examples/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,3 @@ import DraggableCode from "./draggable.vue?raw";
<h3 id="draggable">Draggable rows/columns</h3>
<ExampleViewer :component="Draggable" :code="DraggableCode" />
</template>
./draggable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ const isPaginationSimple = ref(false);
const paginationPosition = ref("bottom");
const sortIcon = ref("arrow-up");
const sortIconSize = ref("small");
const defaultSortDirection = ref("asc");
const defaultSortDirection = ref<"asc" | "desc">("asc");
const currentPage = ref(1);
const perPage = ref(3);
</script>
Expand Down
6 changes: 3 additions & 3 deletions packages/oruga/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1268,10 +1268,10 @@ but will set body to position fixed, might break some layouts. */
hoverable: boolean;
/** Select placeholder text when nothing is selected (if mobileCards) */
mobileSortPlaceholder: string;
/** Sets the default sort column and order — e.g. ['first_name', 'desc'] */
defaultSort: string | string[];
/** Sets the default sort column and order — e.g. 'first_name' or ['first_name', 'desc'] */
defaultSort: string | [string, "asc" | "desc"];
/** Sets the default sort column direction on the first click */
defaultSortDirection: string;
defaultSortDirection: "asc" | "desc";
/** Sets the header sorting icon */
sortIcon: string;
/** Sets the size of the sorting icon */
Expand Down

0 comments on commit e9030bd

Please sign in to comment.