Forward Ref and selection/scrollto

This commit is contained in:
Hein 2025-10-24 16:51:55 +02:00
parent ad5bc14d7c
commit d6b7fa4076
8 changed files with 294 additions and 89 deletions

View File

@ -1,12 +1,14 @@
import '@glideapps/glide-data-grid/dist/index.css'; import '@glideapps/glide-data-grid/dist/index.css';
import React, { type Ref } from 'react';
import { MantineBetterMenusProvider } from '../MantineBetterMenu'; import { MantineBetterMenusProvider } from '../MantineBetterMenu';
import { GlidlerFormAdaptor } from './components/adaptors/GlidlerFormAdaptor'; import { GlidlerFormAdaptor } from './components/adaptors/GlidlerFormAdaptor';
import { GlidlerLocalDataAdaptor } from './components/adaptors/GlidlerLocalDataAdaptor'; import { GlidlerLocalDataAdaptor } from './components/adaptors/GlidlerLocalDataAdaptor';
import { type GridlerProps, Provider } from './components/GridlerStore'; import { type GridlerProps, type GridlerRef, Provider } from './components/GridlerStore';
import { GridlerRefHandler } from './components/RefHandler';
import { GridlerDataGrid } from './GridlerDataGrid'; import { GridlerDataGrid } from './GridlerDataGrid';
const Gridler = (props: GridlerProps) => { const _Gridler = (props: GridlerProps, ref: Ref<GridlerRef> | undefined) => {
return ( return (
<MantineBetterMenusProvider> <MantineBetterMenusProvider>
<Provider <Provider
@ -19,12 +21,20 @@ const Gridler = (props: GridlerProps) => {
}} }}
> >
<GridlerDataGrid /> <GridlerDataGrid />
<GridlerRefHandler ref={ref} />
{props.children} {props.children}
</Provider> </Provider>
</MantineBetterMenusProvider> </MantineBetterMenusProvider>
); );
}; };
type GridlerComponentType = {
FormAdaptor: typeof GlidlerFormAdaptor;
LocalDataAdaptor: typeof GlidlerLocalDataAdaptor;
} & React.ForwardRefExoticComponent<GridlerProps & React.RefAttributes<GridlerRef>>;
const Gridler = React.forwardRef(_Gridler) as GridlerComponentType;
Gridler.FormAdaptor = GlidlerFormAdaptor; Gridler.FormAdaptor = GlidlerFormAdaptor;
Gridler.LocalDataAdaptor = GlidlerLocalDataAdaptor; Gridler.LocalDataAdaptor = GlidlerLocalDataAdaptor;

View File

@ -40,6 +40,7 @@ export const GridlerDataGrid = () => {
const { const {
_gridSelection, _gridSelection,
allowMultiSelect,
focused, focused,
getCellContent, getCellContent,
getCellsForSelection, getCellsForSelection,
@ -69,6 +70,7 @@ export const GridlerDataGrid = () => {
widthProp, widthProp,
} = useGridlerStore((s) => ({ } = useGridlerStore((s) => ({
_gridSelection: s._gridSelection, _gridSelection: s._gridSelection,
allowMultiSelect: s.allowMultiSelect,
focused: s.focused, focused: s.focused,
getCellContent: s.getCellContent, getCellContent: s.getCellContent,
getCellsForSelection: s.getCellsForSelection, getCellsForSelection: s.getCellsForSelection,
@ -157,16 +159,16 @@ export const GridlerDataGrid = () => {
height={height ?? 400} height={height ?? 400}
overscrollX={16} overscrollX={16}
overscrollY={32} overscrollY={32}
rangeSelect="multi-rect" rangeSelect={allowMultiSelect ? 'multi-rect' : 'cell'}
rightElementProps={{ rightElementProps={{
fill: false, fill: false,
sticky: true, sticky: true,
}} }}
rowMarkers={{ rowMarkers={{
checkboxStyle: 'square', checkboxStyle: 'square',
kind: 'both', kind: allowMultiSelect ? 'both' : 'clickable-number',
}} }}
rowSelect="multi" rowSelect={allowMultiSelect ? 'multi' : 'single'}
rowSelectionMode="auto" rowSelectionMode="auto"
spanRangeBehavior="default" spanRangeBehavior="default"
{...glideProps} {...glideProps}

View File

@ -10,32 +10,36 @@ export const Computer = React.memo(() => {
const { const {
_glideref, _glideref,
_gridSelectionRows, _gridSelectionRows,
askAPIRowNumber,
colFilters, colFilters,
colOrder, colOrder,
colSize, colSize,
colSort, colSort,
columns, columns,
getRowIndexByKey,
getState, getState,
loadPage, loadPage,
ready, ready,
scrollToRowKey,
selectedRowKey,
setState, setState,
setStateFN, setStateFN,
values, values,
} = useGridlerStore((s) => ({ } = useGridlerStore((s) => ({
_glideref: s._glideref, _glideref: s._glideref,
_gridSelectionRows: s._gridSelectionRows, _gridSelectionRows: s._gridSelectionRows,
askAPIRowNumber: s.askAPIRowNumber,
colFilters: s.colFilters, colFilters: s.colFilters,
colOrder: s.colOrder, colOrder: s.colOrder,
colSize: s.colSize, colSize: s.colSize,
colSort: s.colSort, colSort: s.colSort,
columns: s.columns, columns: s.columns,
getRowIndexByKey: s.getRowIndexByKey,
getState: s.getState, getState: s.getState,
loadPage: s.loadPage, loadPage: s.loadPage,
ready: s.ready, ready: s.ready,
scrollToRowKey: s.scrollToRowKey,
selectedRowKey: s.selectedRowKey,
setState: s.setState, setState: s.setState,
setStateFN: s.setStateFN, setStateFN: s.setStateFN,
uniqueid: s.uniqueid, uniqueid: s.uniqueid,
@ -72,8 +76,8 @@ export const Computer = React.memo(() => {
break; break;
} }
} }
if (!(rowIndex >= 0) && typeof askAPIRowNumber === 'function') { if (!(rowIndex >= 0)) {
const idx = await askAPIRowNumber(key); const idx = await getRowIndexByKey(key);
if (idx) { if (idx) {
rowIndexes.push(idx); rowIndexes.push(idx);
} }
@ -180,12 +184,14 @@ export const Computer = React.memo(() => {
: (c.defaultIcon ?? 'sort'), : (c.defaultIcon ?? 'sort'),
})); }));
}).then(() => { }).then(() => {
loadPage(0, 'all'); loadPage(0, 'all').then(() => {
getState('_events')?.dispatchEvent?.( getState('refreshCells')?.();
new CustomEvent('onColumnSorted', { getState('_events')?.dispatchEvent?.(
detail: { cols: colSort }, new CustomEvent('onColumnSorted', {
}) detail: { cols: colSort },
); })
);
});
}); });
}, [colSort]); }, [colSort]);
@ -195,13 +201,15 @@ export const Computer = React.memo(() => {
} }
if (JSON.stringify(refLastFilters.current) !== JSON.stringify(colFilters)) { if (JSON.stringify(refLastFilters.current) !== JSON.stringify(colFilters)) {
loadPage(0, 'all'); loadPage(0, 'all').then(() => {
getState('refreshCells')?.();
getState('_events')?.dispatchEvent?.(
new CustomEvent('onColumnFiltered', {
detail: { filters: colFilters },
})
);
});
refLastFilters.current = colFilters; refLastFilters.current = colFilters;
getState('_events')?.dispatchEvent?.(
new CustomEvent('onColumnFiltered', {
detail: { filters: colFilters },
})
);
} }
}, [colFilters]); }, [colFilters]);
@ -214,6 +222,8 @@ export const Computer = React.memo(() => {
...c, ...c,
width: c.id && colSize?.[c.id] ? colSize?.[c.id] : c.width, width: c.id && colSize?.[c.id] ? colSize?.[c.id] : c.width,
})); }));
}).then(() => {
getState('refreshCells')?.();
}); });
}, [colSize]); }, [colSize]);
@ -231,6 +241,8 @@ export const Computer = React.memo(() => {
}); });
return result; return result;
}).then(() => {
getState('refreshCells')?.();
}); });
}, [colOrder]); }, [colOrder]);
@ -242,7 +254,9 @@ export const Computer = React.memo(() => {
return; return;
} }
refFirstRun.current = 1; refFirstRun.current = 1;
loadPage(0); loadPage(0).then(() => {
getState('refreshCells')?.();
});
}, [ready, loadPage]); }, [ready, loadPage]);
useEffect(() => { useEffect(() => {
@ -250,30 +264,29 @@ export const Computer = React.memo(() => {
const loadPage = () => { const loadPage = () => {
const selectFirstRowOnMount = getState('selectFirstRowOnMount'); const selectFirstRowOnMount = getState('selectFirstRowOnMount');
if (selectFirstRowOnMount) { if (selectFirstRowOnMount) {
const selectedRow = getState('selectedRow'); const scrollToRowKey = getState('scrollToRowKey');
if (selectedRow && selectedRow >= 0) { if (scrollToRowKey && scrollToRowKey >= 0) {
return; return;
} }
const keyField = getState('keyField') ?? 'id'; const keyField = getState('keyField') ?? 'id';
const page_data = getState('_page_data'); const page_data = getState('_page_data');
const firstBuffer = page_data?.[0]?.[0]; const firstBuffer = page_data?.[0]?.[0];
const firstRow = firstBuffer?.[keyField]; const firstRow = firstBuffer?.[keyField];
const currentValues = getState('values') ?? [];
if (firstRow && firstRow > 0) { if (firstRow && firstRow > 0 && (currentValues.length ?? 0) === 0) {
const values = [ const values = [firstBuffer, ...(currentValues as Array<Record<string, unknown>>)];
firstBuffer,
...((getState('values') ?? []) as Array<Record<string, unknown>>),
];
const onChange = getState('onChange'); const onChange = getState('onChange');
console.log('Selecting first row:', firstRow, firstBuffer, values); //console.log('Selecting first row:', firstRow, firstBuffer, values);
if (onChange) { if (onChange) {
onChange(values); onChange(values);
} else { } else {
setState('values', values); setState('values', values);
} }
setState('selectedRow', firstRow); setState('scrollToRowKey', firstRow);
} }
} }
}; };
@ -284,6 +297,64 @@ export const Computer = React.memo(() => {
_events?.removeEventListener('loadPage', loadPage); _events?.removeEventListener('loadPage', loadPage);
}; };
}, []); }, []);
/// logic to apply the selected row.
useEffect(() => {
const ready = getState('ready');
const ref = getState('_glideref');
const getRowIndexByKey = getState('getRowIndexByKey');
if (scrollToRowKey && ref && ready) {
getRowIndexByKey?.(scrollToRowKey).then((r) => {
if (r !== undefined) {
console.log('Scrolling to selected row:', scrollToRowKey, r);
ref.scrollTo(0, r);
getState('_events').dispatchEvent(
new CustomEvent('scrollToRowKeyFound', {
detail: { rowNumber: r, scrollToRowKey: scrollToRowKey },
})
);
}
});
}
}, [scrollToRowKey]);
useEffect(() => {
const ready = getState('ready');
const ref = getState('_glideref');
const getRowIndexByKey = getState('getRowIndexByKey');
const key = selectedRowKey ?? scrollToRowKey;
if (key && ref && ready) {
getRowIndexByKey?.(key).then((r) => {
if (r !== undefined) {
console.log('Scrolling to selected row:', r, selectedRowKey, scrollToRowKey);
if (selectedRowKey) {
const onChange = getState('onChange');
const selected = [{ [getState('keyField') ?? 'id']: selectedRowKey }];
if (onChange) {
onChange(selected);
} else {
setState('values', selected);
}
}
ref.scrollTo(0, r);
getState('_events').dispatchEvent(
new CustomEvent('scrollToRowKeyFound', {
detail: {
rowNumber: r,
scrollToRowKey: scrollToRowKey,
selectedRowKey: selectedRowKey,
},
})
);
}
});
}
}, [scrollToRowKey, selectedRowKey]);
// console.log('Gridler:Debug:Computer', { // console.log('Gridler:Debug:Computer', {
// colFilters, // colFilters,
// colOrder, // colOrder,

View File

@ -56,6 +56,7 @@ export type FilterOptionOperator =
| 'startswith'; | 'startswith';
export interface GridlerProps extends PropsWithChildren { export interface GridlerProps extends PropsWithChildren {
allowMultiSelect?: boolean;
columns?: GridlerColumns; columns?: GridlerColumns;
defaultSort?: Array<SortOption>; defaultSort?: Array<SortOption>;
@ -88,6 +89,7 @@ export interface GridlerProps extends PropsWithChildren {
) => GridCell; ) => GridCell;
rowHeight?: number; rowHeight?: number;
scrollToRowKey?: number;
sections?: { sections?: {
bottom?: React.ReactNode; bottom?: React.ReactNode;
left?: React.ReactNode; left?: React.ReactNode;
@ -97,7 +99,7 @@ export interface GridlerProps extends PropsWithChildren {
rightElementStart?: React.ReactNode; rightElementStart?: React.ReactNode;
top?: React.ReactNode; top?: React.ReactNode;
}; };
selectedRow?: number; selectedRowKey?: number;
selectFirstRowOnMount?: boolean; selectFirstRowOnMount?: boolean;
selectMode?: 'cell' | 'row'; selectMode?: 'cell' | 'row';
showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void; showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void;
@ -110,6 +112,17 @@ export interface GridlerProps extends PropsWithChildren {
width?: number | string; 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 { export interface GridlerState {
_active_requests?: Array<{ controller: AbortController; page: number }>; _active_requests?: Array<{ controller: AbortController; page: number }>;
_activeTooltip?: ReactNode; _activeTooltip?: ReactNode;
@ -140,6 +153,7 @@ export interface GridlerState {
abortSignal: AbortSignal abortSignal: AbortSignal
) => CellArray | GetCellsThunk; ) => CellArray | GetCellsThunk;
getRowBuffer: (row: number) => Record<string, any>; getRowBuffer: (row: number) => Record<string, any>;
getRowIndexByKey: (key: number | string) => Promise<number | undefined>;
getState: <K extends keyof GridlerStoreState>(key: K) => GridlerStoreState[K]; getState: <K extends keyof GridlerStoreState>(key: K) => GridlerStoreState[K];
hasLocalData: boolean; hasLocalData: boolean;
@ -174,7 +188,9 @@ export interface GridlerState {
pageSize: number; pageSize: number;
ready: boolean; ready: boolean;
refreshCells: (fromRow?: number, toRow?: number, col?: number) => void;
reload?: () => Promise<void>; reload?: () => Promise<void>;
renderColumns?: GridlerColumns; renderColumns?: GridlerColumns;
setState: <K extends keyof GridlerStoreState>( setState: <K extends keyof GridlerStoreState>(
key: K, key: K,
@ -250,6 +266,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
return result as CellArray; return result as CellArray;
}; };
}, },
getRowBuffer: (row: number) => { getRowBuffer: (row: number) => {
const state = get(); const state = get();
//Handle local data //Handle local data
@ -272,6 +289,43 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
return rowData; 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) => { getState: (key) => {
return get()[key]; return get()[key];
}, },
@ -702,6 +756,30 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
}, },
pageSize: 50, pageSize: 50,
ready: false, 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) => { setState: (key, value) => {
set( set(
produce((state) => { produce((state) => {
@ -816,60 +894,9 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
}; };
}, [setState, getState]); }, [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('_events').addEventListener('reload', (_e: Event) => {
getState('reload')?.(); getState('reload')?.();
getState('refreshCells')?.();
}); });
return { return {
@ -877,6 +904,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
colSort: props.defaultSort ?? getState('colSort') ?? [], colSort: props.defaultSort ?? getState('colSort') ?? [],
hideMenu: props.hideMenu ?? menus.hide, hideMenu: props.hideMenu ?? menus.hide,
scrollToRowKey: props.scrollToRowKey ?? props.selectedRowKey ?? getState('scrollToRowKey'),
showMenu: props.showMenu ?? menus.show, showMenu: props.showMenu ?? menus.show,
total_rows: props.total_rows ?? getState('total_rows') ?? 0, total_rows: props.total_rows ?? getState('total_rows') ?? 0,
}; };

View File

@ -0,0 +1,52 @@
import React, { type PropsWithChildren, type Ref, useImperativeHandle } from 'react';
import { type GridlerRef, useGridlerStore } from './GridlerStore';
function _GridlerRefHandler(props: PropsWithChildren, ref: Ref<GridlerRef> | undefined) {
const [setStateFN, getstate] = useGridlerStore((s) => [s.setStateFN, s.getState]);
useImperativeHandle<GridlerRef, GridlerRef>(ref, () => {
return {
getGlideRef: () => {
return getstate('_glideref');
},
getState: getstate,
refresh: async (parms?: any) => {
const refreshCells = getstate('refreshCells');
const loadPage = getstate('loadPage');
loadPage?.(parms?.pageIndex ?? 0, 'all');
refreshCells?.();
},
reload: async (parms?: any) => {
const refreshCells = getstate('refreshCells');
const loadPage = getstate('loadPage');
loadPage?.(parms?.pageIndex ?? 0, 'all');
refreshCells?.();
},
reloadRow: async (key: number | string) => {
const refreshCells = getstate('refreshCells');
//const loadPage = getstate('loadPage');
const getRowIndexByKey = getstate('getRowIndexByKey');
const rn = await getRowIndexByKey?.(String(key));
if (rn && rn >= 0) {
refreshCells?.(rn, rn + 1);
//todo loadpage or row from server
}
},
scrollToRow: async (key: number | string) => {
if (key && Number(key) >= 0) {
setStateFN('scrollToRowKey', (cv) => Number(key ?? cv));
}
},
selectRow: async (key: number | string) => {
if (key && Number(key) >= 0) {
setStateFN('selectedRowKey', (cv) => Number(key ?? cv));
}
},
setStateFN: setStateFN,
};
}, []);
return <>{props.children}</>;
}
export const GridlerRefHandler = React.forwardRef(_GridlerRefHandler);

View File

@ -56,6 +56,7 @@ function _GlidlerLocalDataAdaptor<T = unknown>(props: GlidlerLocalDataAdaptorPro
setState('total_rows', sortedData.length); setState('total_rows', sortedData.length);
setState('data', sortedData); setState('data', sortedData);
refChanged.current.colSort = colSort; refChanged.current.colSort = colSort;
getState('refreshCells')?.();
} }
}, [colSort, props.onColumnSort]); }, [colSort, props.onColumnSort]);
@ -65,6 +66,7 @@ function _GlidlerLocalDataAdaptor<T = unknown>(props: GlidlerLocalDataAdaptorPro
setState('total_rows', filteredData.length); setState('total_rows', filteredData.length);
setState('data', filteredData); setState('data', filteredData);
refChanged.current.colFilters = colFilters; refChanged.current.colFilters = colFilters;
getState('refreshCells')?.();
} }
}, [colFilters, props.onColumnFilter]); }, [colFilters, props.onColumnFilter]);

View File

@ -102,8 +102,8 @@ export const useGridTheme = () => {
// }[colorScheme]; // }[colorScheme];
// for (const selectedRow of gridSelection?.rows) { // for (const scrollToRowKey of gridSelection?.rows) {
// if (selectedRow === row) { // if (scrollToRowKey === row) {
// return { // return {
// bgCell: rowColor.bgCell, // bgCell: rowColor.bgCell,
// bgCellMedium: rowColor.bgCellMedium // bgCellMedium: rowColor.bgCellMedium

View File

@ -1,10 +1,11 @@
import { Checkbox, Divider, Group, Stack, TagsInput, TextInput } from '@mantine/core'; import { Button, Checkbox, Divider, Group, Stack, TagsInput, TextInput } from '@mantine/core';
import { useLocalStorage } from '@mantine/hooks'; import { useLocalStorage } from '@mantine/hooks';
import { useState } from 'react'; import { useRef, useState } from 'react';
import type { GridlerColumns } from '../components/Column'; import type { GridlerColumns } from '../components/Column';
import { GlidlerAPIAdaptorForGoLangv2 } from '../components/adaptors'; import { GlidlerAPIAdaptorForGoLangv2 } from '../components/adaptors';
import { type GridlerRef } from '../components/GridlerStore';
import { Gridler } from '../Gridler'; import { Gridler } from '../Gridler';
export const GridlerGoAPIExampleEventlog = () => { export const GridlerGoAPIExampleEventlog = () => {
@ -12,6 +13,7 @@ export const GridlerGoAPIExampleEventlog = () => {
defaultValue: 'http://localhost:8080/api', defaultValue: 'http://localhost:8080/api',
key: 'apiurl', key: 'apiurl',
}); });
const ref = useRef<GridlerRef>(null);
const [apiKey, setApiKey] = useLocalStorage({ defaultValue: '', key: 'apikey' }); const [apiKey, setApiKey] = useLocalStorage({ defaultValue: '', key: 'apikey' });
const [selectRow, setSelectRow] = useState<string | undefined>(''); const [selectRow, setSelectRow] = useState<string | undefined>('');
const [values, setValues] = useState<Array<Record<string, any>>>([]); const [values, setValues] = useState<Array<Record<string, any>>>([]);
@ -106,8 +108,9 @@ export const GridlerGoAPIExampleEventlog = () => {
//console.log('GridlerGoAPIExampleEventlog onChange', v); //console.log('GridlerGoAPIExampleEventlog onChange', v);
setValues(v); setValues(v);
}} }}
ref={ref}
scrollToRowKey={selectRow ? parseInt(selectRow, 10) : undefined}
sections={{ ...sections, rightElementDisabled: false }} sections={{ ...sections, rightElementDisabled: false }}
selectedRow={selectRow ? parseInt(selectRow, 10) : undefined}
selectFirstRowOnMount={true} selectFirstRowOnMount={true}
selectMode="row" selectMode="row"
title="Go API Example" title="Go API Example"
@ -142,6 +145,43 @@ export const GridlerGoAPIExampleEventlog = () => {
/> />
; ;
</Group> </Group>
<Group>
<Button
onClick={() => {
ref.current?.refresh();
}}
>
Refresh
</Button>
<Button
onClick={() => {
ref.current?.selectRow(20523);
}}
>
Select 20523
</Button>
<Button
onClick={() => {
ref.current?.selectRow(4);
}}
>
Select 4
</Button>
<Button
onClick={() => {
ref.current?.reloadRow(20523);
}}
>
Reload 20523
</Button>
<Button
onClick={() => {
ref.current?.scrollToRow(16272);
}}
>
Goto 2050
</Button>
</Group>
</Stack> </Stack>
); );
}; };