From 0ee6c5c6e9298c41e78c0fe79b85d8d76758ebd8 Mon Sep 17 00:00:00 2001 From: Chaim Lev-Ari Date: Thu, 24 Aug 2023 15:35:05 +0200 Subject: [PATCH] refactor(ui/datatables): allow to control selected state from parent --- app/react/components/datatables/Datatable.tsx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/app/react/components/datatables/Datatable.tsx b/app/react/components/datatables/Datatable.tsx index 452a8e615..be54a2ad2 100644 --- a/app/react/components/datatables/Datatable.tsx +++ b/app/react/components/datatables/Datatable.tsx @@ -14,6 +14,8 @@ import { getExpandedRowModel, TableOptions, TableMeta, + Updater, + RowSelectionState, } from '@tanstack/react-table'; import { ReactNode, useMemo } from 'react'; import clsx from 'clsx'; @@ -75,6 +77,12 @@ export interface Props< noWidget?: boolean; meta?: TMeta; globalFilterFn?: typeof defaultGlobalFilterFn; + /** + * pass selectedItemIds and onChangeSelectedItems to control selected values from the parent + * usually useful when the table is used in a form + */ + selectedItemIds?: Array; + onChangeSelectedItems?(value: Array): void; } export function Datatable< @@ -107,6 +115,8 @@ export function Datatable< totalCount = dataset.length, isServerSidePagination = false, globalFilterFn = defaultGlobalFilterFn, + selectedItemIds, + onChangeSelectedItems, }: Props & PaginationProps) { const pageCount = useMemo( () => Math.ceil(totalCount / settings.pageSize), @@ -144,6 +154,7 @@ export function Datatable< enableHiding: true, sortingFn: 'alphanumeric', }, + ...getControlledSelectionState(onChangeSelectedItems, selectedItemIds), enableRowSelection, autoResetExpanded: false, globalFilterFn, @@ -230,6 +241,32 @@ export function Datatable< } } +function getControlledSelectionState( + onChange?: (value: string[]) => void, + value?: string[] +) { + if (!onChange || !value) { + return {}; + } + + return { + state: { + rowSelection: Object.fromEntries(value.map((i) => [i, true])), + }, + onRowSelectionChange(updater: Updater) { + const newValue = + typeof updater !== 'function' + ? updater + : updater(Object.fromEntries(value.map((i) => [i, true]))); + onChange( + Object.entries(newValue) + .filter(([, selected]) => selected) + .map(([id]) => id) + ); + }, + }; +} + function defaultRenderRow( row: Row, highlightedItemId?: string