Skip to content

Commit

Permalink
fix(table): solve an issue with isRowChecked prop (#1032)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlmoravek authored Aug 8, 2024
1 parent 39bfbef commit 9bcc478
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 39 deletions.
2 changes: 1 addition & 1 deletion packages/docs/components/Table.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ sidebarDepth: 2
| iconPack | Icon pack to use | string | `mdi`, `fa`, `fas and any other custom icon pack` | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;iconPack: undefined<br>}</code> |
| isDetailedVisible | Controls the visibility of the trigger that toggles the detailed rows (if detailed) | (row: unknown) =&gt; boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;isDetailedVisible: (row) => true<br>}</code> |
| isRowCheckable | Custom method to verify if a row is checkable (if checkable) | (row: unknown) =&gt; boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;isRowCheckable: (row) => true<br>}</code> |
| isRowChecked | Custom method to verify if a row is checked (if checkable). Useful for backend pagination. | (row: unknown, data: unknown[]) =&gt; boolean | - | |
| isRowChecked | Custom method to verify if a row is checked (if checkable) | (row: unknown) =&gt; boolean | - | |
| isRowSelectable | Custom method to verify if a row is selectable, works when is selectable | (row: unknown) =&gt; boolean | - | Default function (see source code) |
| loading | Enable loading state | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| loadingIcon | Icon for the loading state | string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>table: {<br>&nbsp;&nbsp;loadingIcon: "loading"<br>}</code> |
Expand Down
49 changes: 24 additions & 25 deletions packages/oruga/src/components/table/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import OTablePagination from "./TablePagination.vue";
import { getOption } from "@/utils/config";
import {
getValueByPath,
indexOf,
toCssDimension,
escapeRegExpChars,
removeDiacriticsFromString,
Expand Down Expand Up @@ -176,9 +175,9 @@ const props = defineProps({
type: String,
default: () => getOption("table.checkboxVariant"),
},
/** Custom method to verify if a row is checked (if checkable). Useful for backend pagination. */
/** Custom method to verify if a row is checked (if checkable) */
isRowChecked: {
type: Function as PropType<(row: T, data: T[]) => boolean>,
type: Function as PropType<(row: T) => boolean>,
default: undefined,
},
/** Custom method to verify if a row is checkable (if checkable) */
Expand Down Expand Up @@ -953,6 +952,20 @@ function getColumnValue(row: T, column: TableColumn<T>): string {
return getPropertyValue(row, column.field, column.formatter);
}
/** check if two rows are eqal by a custom compare function or the rowKey attribute */
function isRowEqual(
sourceRow: MaybeRefOrGetter<T>,
targetRow?: MaybeRefOrGetter<T>,
): boolean {
const el1 = toValue(sourceRow);
const el2 = toValue(targetRow);
if (!isDefined(targetRow)) return false;
if (typeof props.customCompare === "function")
return props.customCompare(el1, el2);
if (props.rowKey) return el1[props.rowKey] == el2[props.rowKey];
return el1 == el2;
}
// --- Select Feature ---
const tableSelectedRow = defineModel<T>("selected", { default: undefined });
Expand Down Expand Up @@ -1018,19 +1031,6 @@ function selectRow(row: TableRow<T>, index: number, event: Event): void {
emits("select", row.value, tableSelectedRow.value);
}
function isRowEqual(
sourceRow: MaybeRefOrGetter<T>,
targetRow?: MaybeRefOrGetter<T>,
): boolean {
const el1 = toValue(sourceRow);
const el2 = toValue(targetRow);
if (!isDefined(targetRow)) return false;
if (typeof props.customCompare === "function")
return props.customCompare(el1, el2);
if (props.rowKey) return el1[props.rowKey] == el2[props.rowKey];
return el1 == el2;
}
// --- Filter Feature ---
const filters = ref<Record<string, string>>({});
Expand Down Expand Up @@ -1184,13 +1184,8 @@ const isAllChecked = computed(() => {
props.isRowCheckable(row.value),
);
if (validVisibleData.length === 0) return false;
return !validVisibleData.some(
(currentVisibleRow) =>
indexOf(
tableCheckedRows.value,
currentVisibleRow.value,
props.isRowChecked,
) < 0,
return !validVisibleData.some((currentVisibleRow) =>
isChecked(currentVisibleRow),
);
});
Expand All @@ -1201,7 +1196,9 @@ const isAllUncheckable = computed(
/** check if the row is checked (is added to the array) */
function isChecked(row: TableRow<T>): boolean {
return indexOf(tableCheckedRows.value, row.value, props.isRowChecked) >= 0;
if (typeof props.isRowChecked === "function")
return props.isRowChecked(row.value);
else tableCheckedRows.value.some((r) => isRowEqual(r, row.value));
}
/** add a checked row to the the array */
Expand All @@ -1211,7 +1208,9 @@ function addCheckedRow(row: TableRow<T>): void {
/** remove a checked row from the array */
function removeCheckedRow(row: TableRow<T>): void {
const idx = indexOf(tableCheckedRows.value, row.value, props.isRowChecked);
const idx = tableCheckedRows.value.findIndex((r) =>
isRowEqual(r, row.value),
);
if (idx >= 0)
tableCheckedRows.value = tableCheckedRows.value.toSpliced(idx, 1);
}
Expand Down
6 changes: 6 additions & 0 deletions packages/oruga/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,12 @@ but will set body to position fixed, might break some layouts. */
filterIcon: string;
/** Icon pack to use */
iconPack: string;
/** Icon to be shown when the table is empty */
emptyIcon: string;
/** Label for the loading state */
loadingLabel: string;
/** Label to be shown when the table is empty */
emptyLabel: string;
/** Makes the cells narrower */
narrowed: boolean;
/** Mobile breakpoint as `max-width` value */
Expand Down Expand Up @@ -1282,6 +1286,8 @@ but will set body to position fixed, might break some layouts. */
sortIconSize: string;
/** Show header */
showHeader: boolean;
/** Size of empty icon */
emptyIconSize: string;
/** Size of pagination (if paginated) */
paginationSize: string;
/** Table can be focused and user can select rows. Rows can be navigate with keyboard arrows and are highlighted when hovering. */
Expand Down
13 changes: 0 additions & 13 deletions packages/oruga/src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,6 @@ export const defaultIfUndefined = <T>(
export const toCssDimension = (width: string | number): string | number =>
!isDefined(width) ? null : isNaN(width as number) ? width : width + "px";

/**
* Extension of indexOf method by equality function if specified
*/
export function indexOf<T>(
array: T[],
obj: T,
fn: (value: T, array: T[]) => boolean,
): number {
if (!array) return -1;
if (!fn || typeof fn !== "function") return array.indexOf(obj);
return array.findIndex((value, index, arr) => fn(value, arr));
}

/**
* Sort an array by key without mutating original data.
* Call the user sort function if it was passed.
Expand Down

0 comments on commit 9bcc478

Please sign in to comment.