Forward Ref and selection/scrollto
This commit is contained in:
@@ -56,6 +56,7 @@ export type FilterOptionOperator =
|
||||
| 'startswith';
|
||||
|
||||
export interface GridlerProps extends PropsWithChildren {
|
||||
allowMultiSelect?: boolean;
|
||||
columns?: GridlerColumns;
|
||||
|
||||
defaultSort?: Array<SortOption>;
|
||||
@@ -88,6 +89,7 @@ export interface GridlerProps extends PropsWithChildren {
|
||||
) => GridCell;
|
||||
|
||||
rowHeight?: number;
|
||||
scrollToRowKey?: number;
|
||||
sections?: {
|
||||
bottom?: React.ReactNode;
|
||||
left?: React.ReactNode;
|
||||
@@ -97,7 +99,7 @@ export interface GridlerProps extends PropsWithChildren {
|
||||
rightElementStart?: React.ReactNode;
|
||||
top?: React.ReactNode;
|
||||
};
|
||||
selectedRow?: number;
|
||||
selectedRowKey?: number;
|
||||
selectFirstRowOnMount?: boolean;
|
||||
selectMode?: 'cell' | 'row';
|
||||
showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void;
|
||||
@@ -110,6 +112,17 @@ export interface GridlerProps extends PropsWithChildren {
|
||||
width?: number | string;
|
||||
}
|
||||
|
||||
export interface GridlerRef {
|
||||
getGlideRef: () => DataEditorRef | undefined;
|
||||
getState: GridlerState['getState'];
|
||||
refresh: (parms?: any) => Promise<void>;
|
||||
reload: (parms?: any) => Promise<void>;
|
||||
reloadRow: (key: number | string) => Promise<void>;
|
||||
scrollToRow: (key: number | string) => Promise<void>;
|
||||
selectRow: (key: number | string) => Promise<void>;
|
||||
setStateFN: GridlerState['setStateFN'];
|
||||
}
|
||||
|
||||
export interface GridlerState {
|
||||
_active_requests?: Array<{ controller: AbortController; page: number }>;
|
||||
_activeTooltip?: ReactNode;
|
||||
@@ -140,6 +153,7 @@ export interface GridlerState {
|
||||
abortSignal: AbortSignal
|
||||
) => CellArray | GetCellsThunk;
|
||||
getRowBuffer: (row: number) => Record<string, any>;
|
||||
getRowIndexByKey: (key: number | string) => Promise<number | undefined>;
|
||||
getState: <K extends keyof GridlerStoreState>(key: K) => GridlerStoreState[K];
|
||||
hasLocalData: boolean;
|
||||
|
||||
@@ -174,7 +188,9 @@ export interface GridlerState {
|
||||
pageSize: number;
|
||||
|
||||
ready: boolean;
|
||||
refreshCells: (fromRow?: number, toRow?: number, col?: number) => void;
|
||||
reload?: () => Promise<void>;
|
||||
|
||||
renderColumns?: GridlerColumns;
|
||||
setState: <K extends keyof GridlerStoreState>(
|
||||
key: K,
|
||||
@@ -250,6 +266,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
return result as CellArray;
|
||||
};
|
||||
},
|
||||
|
||||
getRowBuffer: (row: number) => {
|
||||
const state = get();
|
||||
//Handle local data
|
||||
@@ -272,6 +289,43 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
|
||||
return rowData;
|
||||
},
|
||||
getRowIndexByKey: async (key: number | string) => {
|
||||
const state = get();
|
||||
|
||||
let rowIndex = -1;
|
||||
if (state.ready) {
|
||||
const page_data = state._page_data;
|
||||
const pageSize = state.pageSize;
|
||||
const keyField = state.keyField ?? 'id';
|
||||
for (const p in page_data) {
|
||||
for (const r in page_data[p]) {
|
||||
const idx = Number(p) * pageSize + Number(r);
|
||||
//console.log('Found row', idx, page_data[p][r]?.[keyField], scrollToRowKey);
|
||||
if (String(page_data[p][r]?.[keyField]) === String(key)) {
|
||||
rowIndex =
|
||||
page_data[p][r]?._rownumber > 0 ? page_data[p][r]?._rownumber : idx > 0 ? idx : -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rowIndex > 0) {
|
||||
console.log('Local row index', rowIndex, key);
|
||||
return rowIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (rowIndex > 0) {
|
||||
return rowIndex;
|
||||
} else if (typeof state.askAPIRowNumber === 'function') {
|
||||
const rn = await state.askAPIRowNumber(String(key));
|
||||
if (rn && rn >= 0) {
|
||||
console.log('Remote row index', rowIndex, key);
|
||||
return rn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
getState: (key) => {
|
||||
return get()[key];
|
||||
},
|
||||
@@ -702,6 +756,30 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
},
|
||||
pageSize: 50,
|
||||
ready: false,
|
||||
refreshCells: (fromRow?: number, toRow?: number, col?: number) => {
|
||||
const state = get();
|
||||
const damageList: { cell: [number, number] }[] = [];
|
||||
const colLen = Object.keys(state.renderColumns ?? [1, 2, 3]).length;
|
||||
|
||||
const from = fromRow && fromRow > 0 ? fromRow : 0;
|
||||
const to = toRow && toRow >= from ? toRow : from + state.pageSize;
|
||||
|
||||
for (let row = from; row <= to; row++) {
|
||||
if (col && col > 0) {
|
||||
damageList.push({
|
||||
cell: [col, row],
|
||||
});
|
||||
} else {
|
||||
for (let c = 0; c <= colLen; c++) {
|
||||
damageList.push({
|
||||
cell: [c, row],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state._glideref?.updateCells(damageList);
|
||||
},
|
||||
setState: (key, value) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
@@ -816,60 +894,9 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
};
|
||||
}, [setState, getState]);
|
||||
|
||||
/// logic to apply the selected row.
|
||||
useEffect(() => {
|
||||
const ready = getState('ready');
|
||||
const ref = getState('_glideref');
|
||||
const keyField = getState('keyField') ?? 'id';
|
||||
const selectedRow = getState('selectedRow') ?? props.selectedRow;
|
||||
const askAPIRowNumber = getState('askAPIRowNumber');
|
||||
let rowIndex = -1;
|
||||
if (selectedRow && ref && ready) {
|
||||
const page_data = getState('_page_data');
|
||||
const pageSize = getState('pageSize');
|
||||
for (const p in page_data) {
|
||||
for (const r in page_data[p]) {
|
||||
const idx = Number(p) * pageSize + Number(r);
|
||||
//console.log('Found row', idx, page_data[p][r]?.[keyField], selectedRow);
|
||||
if (String(page_data[p][r]?.[keyField]) === String(selectedRow)) {
|
||||
rowIndex =
|
||||
page_data[p][r]?._rownumber > 0 ? page_data[p][r]?._rownumber : idx > 0 ? idx : -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rowIndex > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rowIndex > 0) {
|
||||
ref.scrollTo(0, rowIndex);
|
||||
getState('_events').dispatchEvent(
|
||||
new CustomEvent('selectedRowFound', {
|
||||
detail: { rowNumber: rowIndex, selectedRow: selectedRow },
|
||||
})
|
||||
);
|
||||
} else if (typeof askAPIRowNumber === 'function') {
|
||||
askAPIRowNumber(String(selectedRow))
|
||||
.then((r) => {
|
||||
if (r >= 0) {
|
||||
ref.scrollTo(0, r);
|
||||
getState('_events').dispatchEvent(
|
||||
new CustomEvent('selectedRowFound', {
|
||||
detail: { rowNumber: r, selectedRow: selectedRow },
|
||||
})
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.warn('Error in askAPIRowNumber', e);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [props.selectedRow]);
|
||||
|
||||
getState('_events').addEventListener('reload', (_e: Event) => {
|
||||
getState('reload')?.();
|
||||
getState('refreshCells')?.();
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -877,6 +904,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
|
||||
colSort: props.defaultSort ?? getState('colSort') ?? [],
|
||||
hideMenu: props.hideMenu ?? menus.hide,
|
||||
scrollToRowKey: props.scrollToRowKey ?? props.selectedRowKey ?? getState('scrollToRowKey'),
|
||||
showMenu: props.showMenu ?? menus.show,
|
||||
total_rows: props.total_rows ?? getState('total_rows') ?? 0,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user