Skip to content

Commit 63809a3

Browse files
Adding new props to the data editor for exposing grid selections (#6028)
* Adding Missing Props and Event for Grid Selection * Clearer Code Comments on the options of the literals * Update dataeditor.py * Update dataeditor.py * Update dataeditor.py * Update dataeditor.py * working select and deselect at the row level * Cleaned up the code, removed logs etc * Update dataeditor.py * Linting * pre-commit fixup --------- Co-authored-by: Masen Furer <[email protected]>
1 parent 3beb1a6 commit 63809a3

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

pyi_hashes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"reflex/components/core/window_events.pyi": "af33ccec866b9540ee7fbec6dbfbd151",
2424
"reflex/components/datadisplay/__init__.pyi": "52755871369acbfd3a96b46b9a11d32e",
2525
"reflex/components/datadisplay/code.pyi": "b86769987ef4d1cbdddb461be88539fd",
26-
"reflex/components/datadisplay/dataeditor.pyi": "35391d4ba147cf20ce4ac7a782066d61",
26+
"reflex/components/datadisplay/dataeditor.pyi": "fb26f3e702fcb885539d1cf82a854be3",
2727
"reflex/components/datadisplay/shiki_code_block.pyi": "1d53e75b6be0d3385a342e7b3011babd",
2828
"reflex/components/el/__init__.pyi": "0adfd001a926a2a40aee94f6fa725ecc",
2929
"reflex/components/el/element.pyi": "c5974a92fbc310e42d0f6cfdd13472f4",

reflex/components/datadisplay/dataeditor.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from reflex.utils.serializers import serializer
1616
from reflex.vars import get_unique_variable_name
1717
from reflex.vars.base import Var
18+
from reflex.vars.function import FunctionStringVar
1819
from reflex.vars.sequence import ArrayVar
1920

2021

@@ -260,6 +261,12 @@ class DataEditor(NoSSRComponent):
260261
# Allow columns selections. ("none", "single", "multi")
261262
column_select: Var[Literal["none", "single", "multi"]]
262263

264+
# Allow range selections. ("none", "cell", "rect", "multi-cell", "multi-rect").
265+
range_select: Var[Literal["none", "cell", "rect", "multi-cell", "multi-rect"]]
266+
267+
# Allow row selections. ("none", "single", "multi").
268+
row_select: Var[Literal["none", "single", "multi"]]
269+
263270
# Prevent diagonal scrolling.
264271
prevent_diagonal_scrolling: Var[bool]
265272

@@ -275,6 +282,18 @@ class DataEditor(NoSSRComponent):
275282
# Initial scroll offset on the vertical axis.
276283
scroll_offset_y: Var[int]
277284

285+
# Controls which types of range selections can exist at the same time. ("exclusive", "mixed").
286+
range_selection_blending: Var[Literal["exclusive", "mixed"]]
287+
288+
# Controls which types of column selections can exist at the same time. ("exclusive", "mixed").
289+
column_selection_blending: Var[Literal["exclusive", "mixed"]]
290+
291+
# Controls which types of row selections can exist at the same time. ("exclusive", "mixed").
292+
row_selection_blending: Var[Literal["exclusive", "mixed"]]
293+
294+
# Controls how spans are handled in selections. ("default", "allowPartial").
295+
span_range_behavior: Var[Literal["default", "allowPartial"]]
296+
278297
# global theme
279298
theme: Var[DataEditorTheme | dict]
280299

@@ -326,6 +345,12 @@ class DataEditor(NoSSRComponent):
326345
# Fired when a row is appended.
327346
on_row_appended: EventHandler[no_args_event_spec]
328347

348+
# The current grid selection state (columns, rows, and current cell/range). Must be used when on_grid_selection_change is used otherwise updates will not be reflected in the grid.
349+
grid_selection: Var[GridSelection]
350+
351+
# Fired when the grid selection changes. Will pass the current selection, the selected columns and the selected rows.
352+
on_grid_selection_change: EventHandler[passthrough_event_spec(GridSelection)]
353+
329354
# Fired when the selection is cleared.
330355
on_selection_cleared: EventHandler[no_args_event_spec]
331356

@@ -342,12 +367,61 @@ def add_imports(self) -> ImportDict:
342367
return {}
343368
return {
344369
"": f"{format.format_library_name(self.library)}/dist/index.css",
345-
self.library: "GridCellKind",
370+
self.library: ["GridCellKind", "CompactSelection"],
346371
"$/utils/helpers/dataeditor.js": ImportVar(
347372
tag="formatDataEditorCells", is_default=False, install=False
348373
),
349374
}
350375

376+
def add_custom_code(self) -> list[str]:
377+
"""Add custom code for reconstructing GridSelection with CompactSelection objects.
378+
379+
Note: When using on_grid_selection_change, Glide Data Grid will not update its internal selection state automatically. Instead,
380+
the grid_selection prop must be updated with a GridSelection object that has CompactSelection objects for the columns and rows properties.
381+
This function provides the necessary JavaScript code to reconstruct the GridSelection object from a dict representation.
382+
383+
Returns:
384+
JavaScript code to reconstruct GridSelection.
385+
"""
386+
return [
387+
"""
388+
function reconstructGridSelection(selection) {
389+
if (!selection || typeof selection !== 'object') {
390+
return undefined;
391+
}
392+
393+
const reconstructCompactSelection = (data) => {
394+
if (!data || !data.items || !Array.isArray(data.items)) {
395+
return CompactSelection.empty();
396+
}
397+
398+
const items = data.items;
399+
if (items.length === 0) {
400+
return CompactSelection.empty();
401+
}
402+
403+
let result = CompactSelection.empty();
404+
405+
// Items are stored as [start, end) ranges in CompactSelection internal format
406+
for (const item of items) {
407+
if (Array.isArray(item) && item.length === 2) {
408+
const [start, end] = item;
409+
result = result.add([start, end]);
410+
}
411+
}
412+
413+
return result;
414+
};
415+
416+
return {
417+
current: selection.current || undefined,
418+
columns: reconstructCompactSelection(selection.columns),
419+
rows: reconstructCompactSelection(selection.rows)
420+
};
421+
}
422+
"""
423+
]
424+
351425
def add_hooks(self) -> list[str]:
352426
"""Get the hooks to render.
353427
@@ -429,6 +503,15 @@ def create(cls, *children, **props) -> Component:
429503
console.warn(
430504
"get_cell_content is not user configurable, the provided value will be discarded"
431505
)
506+
507+
# Apply the reconstruction function to grid_selection if it's a Var
508+
if (grid_selection := props.get("grid_selection")) is not None and isinstance(
509+
grid_selection, Var
510+
):
511+
props["grid_selection"] = FunctionStringVar.create(
512+
"reconstructGridSelection"
513+
).call(grid_selection)
514+
432515
grid = super().create(*children, **props)
433516
return Div.create(
434517
grid,

0 commit comments

Comments
 (0)