docs(changeset): Fixed search and allow row selection for only rows with keys

This commit is contained in:
Hein 2025-10-30 10:42:07 +02:00
parent 0943ffc483
commit b4058f1ef3
5 changed files with 42 additions and 17 deletions

View File

@ -0,0 +1,5 @@
---
'@warkypublic/oranguru': patch
---
Fixed search and allow row selection for only rows with keys

View File

@ -197,7 +197,13 @@ export const GridlerDataGrid = () => {
onGridSelectionChange={(selection) => { onGridSelectionChange={(selection) => {
let rows = CompactSelection.empty(); let rows = CompactSelection.empty();
const currentSelection = getState('_gridSelection'); const currentSelection = getState('_gridSelection');
const keyField = getState('keyField') ?? 'id';
const getRowBuffer = getState('getRowBuffer');
for (const r of selection.rows) { for (const r of selection.rows) {
const validRowID = getRowBuffer ? getRowBuffer(r)?.[keyField] : null;
if (!validRowID) {
continue;
}
rows = rows.hasIndex(r) ? rows : rows.add(r); rows = rows.hasIndex(r) ? rows : rows.add(r);
} }
if (selectMode === 'row' && selection.current?.range) { if (selectMode === 'row' && selection.current?.range) {
@ -206,6 +212,10 @@ export const GridlerDataGrid = () => {
y < selection.current.range.y + selection.current.range.height; y < selection.current.range.y + selection.current.range.height;
y++ y++
) { ) {
const validRowID = getRowBuffer ? getRowBuffer(y)?.[keyField] : null;
if (!validRowID) {
continue;
}
rows = rows.hasIndex(y) ? rows : rows.add(y); rows = rows.hasIndex(y) ? rows : rows.add(y);
} }
} }

View File

@ -1,5 +1,5 @@
import { CompactSelection } from '@glideapps/glide-data-grid'; import { CompactSelection } from '@glideapps/glide-data-grid';
import { useDebouncedValue } from '@mantine/hooks'; import { useDebouncedCallback } from '@mantine/hooks';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { useGridlerStore } from './GridlerStore'; import { useGridlerStore } from './GridlerStore';
@ -7,6 +7,7 @@ import { useGridlerStore } from './GridlerStore';
//The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders. //The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders.
export const Computer = React.memo(() => { export const Computer = React.memo(() => {
const refFirstRun = useRef(0); const refFirstRun = useRef(0);
const refLastSearch = useRef('');
const refLastFilters = useRef<unknown>(null); const refLastFilters = useRef<unknown>(null);
const { const {
_glideref, _glideref,
@ -49,9 +50,22 @@ export const Computer = React.memo(() => {
values: s.values, values: s.values,
})); }));
const debouncedSearchStr = useDebouncedValue(searchStr, 400, { const debouncedDoSearch = useDebouncedCallback(
leading: true, (searchStr: string) => {
}); loadPage(0, 'all').then(() => {
getState('refreshCells')?.();
getState('_events')?.dispatchEvent?.(
new CustomEvent('onSearched', {
detail: { search: searchStr },
})
);
});
},
{
delay: 300,
leading: false,
}
);
useEffect(() => { useEffect(() => {
const searchSelection = async () => { const searchSelection = async () => {
@ -169,19 +183,15 @@ export const Computer = React.memo(() => {
}, [columns]); }, [columns]);
useEffect(() => { useEffect(() => {
if (debouncedSearchStr === undefined || debouncedSearchStr === null) { if (searchStr === undefined || searchStr === null) {
refLastSearch.current = '';
return; return;
} }
if (refLastSearch.current !== searchStr) {
loadPage(0, 'all').then(() => { debouncedDoSearch(searchStr);
getState('refreshCells')?.(); refLastSearch.current = searchStr;
getState('_events')?.dispatchEvent?.( }
new CustomEvent('onSearched', { }, [searchStr]);
detail: { search: debouncedSearchStr },
})
);
});
}, [debouncedSearchStr]);
useEffect(() => { useEffect(() => {
if (!colSort) { if (!colSort) {

View File

@ -916,7 +916,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
hideMenu: props.hideMenu ?? menus.hide, hideMenu: props.hideMenu ?? menus.hide,
scrollToRowKey: props.scrollToRowKey ?? props.selectedRowKey ?? getState('scrollToRowKey'), 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: getState('total_rows') ?? props.total_rows,
}; };
} }
); );

View File

@ -2,7 +2,7 @@ export {GlidlerAPIAdaptorForGoLangv2 } from './components/adaptors/GlidlerAPIAda
export {GlidlerFormAdaptor } from './components/adaptors/GlidlerFormAdaptor' export {GlidlerFormAdaptor } from './components/adaptors/GlidlerFormAdaptor'
export {GlidlerLocalDataAdaptor } from './components/adaptors/GlidlerLocalDataAdaptor' export {GlidlerLocalDataAdaptor } from './components/adaptors/GlidlerLocalDataAdaptor'
export * from './components/Column' export * from './components/Column'
export {type GridlerProps,type GridlerState, useGridlerStore } from './components/GridlerStore' export {type GridlerProps,type GridlerRef,type GridlerState, useGridlerStore } from './components/GridlerStore'
export { GridlerRightMenuIcon } from './components/RightMenuIcon' export { GridlerRightMenuIcon } from './components/RightMenuIcon'
export {Gridler} from './Gridler' export {Gridler} from './Gridler'
export * from './utils' export * from './utils'