Skip to content

Commit fb98286

Browse files
devin-ai-integration[bot]thomas@reflex.devLendemor
authored
Add cell selection documentation for AG Grid (#1543)
* Add cell selection documentation for AG Grid - Create comprehensive cell selection documentation page - Include basic cell selection, range selection, and fill handle examples - Add fill handle configuration with mode: 'fill' as requested - Document requirement for enable_range_selection=True with fill handle - Explain on_cell_value_changed event triggering for fill operations - Add working interactive examples with state management - Update sidebar navigation to include new cell selection page - Include best practices and key features sections Co-Authored-By: [email protected] <[email protected]> * Fix documentation: enable_range_selection not mandatory for fill handle - Corrected statement that enable_range_selection is required for fill handle - Updated to clarify that enable_range_selection enhances but doesn't require fill handle functionality - Based on user testing feedback Co-Authored-By: [email protected] <[email protected]> * Remove all enable_range_selection references from AG Grid cell selection docs - Remove invalid enable_range_selection prop from all examples - Update documentation to reflect that range selection is automatic with cell_selection=True - Address GitHub comment feedback from Lendemor on PR #1543 - Ensure all examples use only valid AG Grid props Co-Authored-By: [email protected] <[email protected]> * Combine redundant Basic and Range Selection sections - Merge Basic Cell Selection and Range Selection into single Cell Selection section - Rename Range Selection to Advanced Selection Event Handling for clarity - Rename Advanced Cell Selection Configuration to Advanced Configuration Options - Address GitHub comment feedback from Lendemor about section redundancy - Maintain all functionality while improving documentation structure Co-Authored-By: [email protected] <[email protected]> * Fix redundant heading hierarchy: change duplicate Cell Selection to Range Selection Co-Authored-By: [email protected] <[email protected]> * Address PR feedback: display ranges data in toast instead of count Co-Authored-By: [email protected] <[email protected]> * Remove misleading note about cell_selection=True being sufficient for fill handle Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: [email protected] <[email protected]> Co-authored-by: Thomas Brandého <[email protected]>
1 parent eedf5e5 commit fb98286

File tree

2 files changed

+292
-0
lines changed

2 files changed

+292
-0
lines changed
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
---
2+
title: "Cell Selection"
3+
order: 8
4+
---
5+
6+
```python exec
7+
from pcweb.pages.docs import enterprise
8+
```
9+
10+
# Cell Selection
11+
12+
AG Grid provides powerful cell selection capabilities that allow users to select individual cells or ranges of cells. This feature is essential for data manipulation, copying, and advanced interactions like fill handle operations.
13+
14+
## Range Selection
15+
16+
To enable cell selection in your AG Grid, set the `cell_selection` prop to `True`. This automatically enables both single cell selection and range selection capabilities.
17+
18+
### Basic Selection Example
19+
20+
```python demo exec
21+
import reflex as rx
22+
import reflex_enterprise as rxe
23+
import pandas as pd
24+
25+
class CellSelectionState(rx.State):
26+
data: list[dict] = []
27+
28+
@rx.event
29+
def load_data(self):
30+
df = pd.read_json("https://www.ag-grid.com/example-assets/olympic-winners.json")
31+
self.data = df.head(10).to_dict("records")
32+
33+
@rx.event
34+
def echo_selection(self, ranges: list[dict], started: bool, finished: bool):
35+
if finished:
36+
yield rx.toast(f"Selected ranges: {ranges}")
37+
38+
column_defs = [
39+
{"field": "athlete", "width": 150},
40+
{"field": "age", "width": 90},
41+
{"field": "country", "width": 120},
42+
{"field": "year", "width": 90},
43+
{"field": "sport", "width": 120},
44+
{"field": "gold", "width": 100},
45+
{"field": "silver", "width": 100},
46+
{"field": "bronze", "width": 100},
47+
]
48+
49+
def basic_cell_selection():
50+
return rx.vstack(
51+
rx.text("Click and drag to select cells. Selection info will appear in a toast.", size="2"),
52+
rxe.ag_grid(
53+
id="basic_cell_selection_grid",
54+
column_defs=column_defs,
55+
row_data=CellSelectionState.data,
56+
cell_selection=True,
57+
on_cell_selection_changed=CellSelectionState.echo_selection,
58+
width="100%",
59+
height="400px",
60+
),
61+
on_mount=CellSelectionState.load_data,
62+
width="100%",
63+
)
64+
```
65+
66+
### Advanced Selection Event Handling
67+
68+
For more sophisticated selection handling, you can process the selection ranges to calculate detailed information:
69+
70+
```python demo exec
71+
import reflex as rx
72+
import reflex_enterprise as rxe
73+
import pandas as pd
74+
75+
class AdvancedSelectionState(rx.State):
76+
data: list[dict] = []
77+
78+
@rx.event
79+
def load_data(self):
80+
df = pd.DataFrame({
81+
"name": ["Alice", "Bob", "Charlie", "Diana", "Eve"],
82+
"score": [85, 92, 78, 96, 88],
83+
"grade": ["B", "A", "C", "A", "B"],
84+
"attempts": [3, 2, 4, 1, 3]
85+
})
86+
self.data = df.to_dict("records")
87+
88+
@rx.event
89+
def handle_selection(self, ranges: list[dict], started: bool, finished: bool):
90+
if finished and ranges:
91+
total_cells = sum(
92+
(r.get("endRow", 0) - r.get("startRow", 0) + 1) *
93+
len(r.get("columns", []))
94+
for r in ranges
95+
)
96+
yield rx.toast(f"Selected {total_cells} cells across {len(ranges)} ranges")
97+
98+
editable_column_defs = [
99+
{"field": "name", "width": 120},
100+
{"field": "score", "width": 100, "editable": True},
101+
{"field": "grade", "width": 100, "editable": True},
102+
{"field": "attempts", "width": 120, "editable": True},
103+
]
104+
105+
def advanced_selection_example():
106+
return rx.vstack(
107+
rx.text("Select ranges of cells. Try selecting multiple ranges by holding Ctrl/Cmd.", size="2"),
108+
rxe.ag_grid(
109+
id="advanced_selection_grid",
110+
column_defs=editable_column_defs,
111+
row_data=AdvancedSelectionState.data,
112+
cell_selection=True,
113+
on_cell_selection_changed=AdvancedSelectionState.handle_selection,
114+
width="100%",
115+
height="300px",
116+
),
117+
on_mount=AdvancedSelectionState.load_data,
118+
width="100%",
119+
)
120+
```
121+
122+
## Fill Handle
123+
124+
The fill handle is a powerful feature that allows users to quickly fill cells by dragging from a selected cell or range. When enabled, a small square appears at the bottom-right corner of the selection that users can drag to fill adjacent cells.
125+
126+
### Enabling Fill Handle
127+
128+
To enable the fill handle, configure the `cell_selection` prop with a dictionary containing the handle configuration:
129+
130+
```python
131+
cell_selection={
132+
"handle": {
133+
"mode": "fill", # Enable fill handle
134+
}
135+
}
136+
```
137+
138+
### Fill Handle Events
139+
140+
When using the fill handle, it will trigger `on_cell_value_changed` for each cell receiving a fill value. This allows your backend to handle the data changes appropriately.
141+
142+
```python demo exec
143+
import reflex as rx
144+
import reflex_enterprise as rxe
145+
import pandas as pd
146+
147+
class FillHandleState(rx.State):
148+
data: list[dict] = []
149+
change_log: list[str] = []
150+
151+
@rx.event
152+
def load_data(self):
153+
df = pd.DataFrame({
154+
"item": ["Apple", "Banana", "Cherry", "Date", "Elderberry"],
155+
"quantity": [10, 15, 8, 12, 20],
156+
"price": [1.50, 0.75, 2.00, 3.00, 4.50],
157+
"total": [15.00, 11.25, 16.00, 36.00, 90.00]
158+
})
159+
self.data = df.to_dict("records")
160+
161+
@rx.event
162+
def handle_cell_change(self, data: dict):
163+
row_index = data.get("rowIndex", 0)
164+
field = data.get("colId", "")
165+
new_value = data.get("newValue", "")
166+
old_value = data.get("oldValue", "")
167+
168+
change_msg = f"Row {row_index + 1}, {field}: '{old_value}' → '{new_value}'"
169+
self.change_log = [change_msg] + self.change_log[:9] # Keep last 10 changes
170+
171+
# Update the data
172+
if 0 <= row_index < len(self.data):
173+
self.data[row_index][field] = new_value
174+
175+
fill_column_defs = [
176+
{"field": "item", "width": 120},
177+
{"field": "quantity", "width": 100, "editable": True, "type": "numericColumn"},
178+
{"field": "price", "width": 100, "editable": True, "type": "numericColumn"},
179+
{"field": "total", "width": 100, "editable": True, "type": "numericColumn"},
180+
]
181+
182+
def fill_handle_example():
183+
return rx.vstack(
184+
rx.text("Select a cell and drag the fill handle (small square at bottom-right) to fill adjacent cells.", size="2"),
185+
rxe.ag_grid(
186+
id="fill_handle_grid",
187+
column_defs=fill_column_defs,
188+
row_data=FillHandleState.data,
189+
cell_selection={
190+
"handle": {
191+
"mode": "fill", # Enable fill handle
192+
}
193+
},
194+
on_cell_value_changed=FillHandleState.handle_cell_change,
195+
width="100%",
196+
height="300px",
197+
),
198+
rx.divider(),
199+
rx.text("Recent Changes:", weight="bold", size="3"),
200+
rx.cond(
201+
FillHandleState.change_log,
202+
rx.vstack(
203+
rx.foreach(
204+
FillHandleState.change_log,
205+
lambda change: rx.text(change, size="1", color="gray")
206+
),
207+
spacing="1",
208+
),
209+
rx.text("No changes yet", size="2", color="gray")
210+
),
211+
on_mount=FillHandleState.load_data,
212+
width="100%",
213+
spacing="4",
214+
)
215+
```
216+
217+
## Advanced Configuration Options
218+
219+
You can further customize cell selection behavior using additional configuration options:
220+
221+
```python demo exec
222+
import reflex as rx
223+
import reflex_enterprise as rxe
224+
import pandas as pd
225+
226+
class ConfigurationState(rx.State):
227+
data: list[dict] = []
228+
229+
@rx.event
230+
def load_data(self):
231+
df = pd.DataFrame({
232+
"id": range(1, 8),
233+
"name": ["Product A", "Product B", "Product C", "Product D", "Product E", "Product F", "Product G"],
234+
"category": ["Electronics", "Clothing", "Electronics", "Books", "Clothing", "Electronics", "Books"],
235+
"price": [299.99, 49.99, 199.99, 24.99, 79.99, 399.99, 19.99],
236+
"stock": [15, 32, 8, 45, 23, 12, 67]
237+
})
238+
self.data = df.to_dict("records")
239+
240+
configuration_column_defs = [
241+
{"field": "id", "width": 80},
242+
{"field": "name", "width": 150, "editable": True},
243+
{"field": "category", "width": 120},
244+
{"field": "price", "width": 100, "editable": True, "type": "numericColumn"},
245+
{"field": "stock", "width": 100, "editable": True, "type": "numericColumn"},
246+
]
247+
248+
def configuration_example():
249+
return rx.vstack(
250+
rx.text("Cell selection with additional configuration options", size="2"),
251+
rxe.ag_grid(
252+
id="configuration_grid",
253+
column_defs=configuration_column_defs,
254+
row_data=ConfigurationState.data,
255+
cell_selection={
256+
"handle": {
257+
"mode": "fill",
258+
}
259+
},
260+
enable_cell_text_selection=True, # Allow text selection within cells
261+
suppress_cell_focus=False, # Allow cell focus
262+
width="100%",
263+
height="350px",
264+
),
265+
on_mount=ConfigurationState.load_data,
266+
width="100%",
267+
)
268+
```
269+
270+
## Key Features
271+
272+
- **Cell Selection**: Enable with `cell_selection=True` for both single cell and range selection capabilities
273+
- **Fill Handle**: Configure with `cell_selection={"handle": {"mode": "fill"}}` for drag-to-fill functionality
274+
- **Event Handling**: Use `on_cell_selection_changed` to respond to selection changes
275+
- **Value Changes**: Use `on_cell_value_changed` to handle individual cell edits and fill operations
276+
- **Text Selection**: Enable `enable_cell_text_selection=True` to allow text selection within cells
277+
278+
## Best Practices
279+
280+
1. **Use cell_selection configuration**: Both single cell and range selection are automatically enabled with `cell_selection=True`, providing all necessary selection capabilities for fill operations.
281+
282+
2. **Handle cell value changes**: When using fill handle, implement `on_cell_value_changed` to process the data updates in your backend.
283+
284+
3. **Provide user feedback**: Use toasts or other UI elements to confirm selection actions and data changes.
285+
286+
4. **Consider performance**: For large datasets, be mindful of the performance impact of frequent cell value change events.
287+
288+
5. **Validate fill operations**: Implement validation logic in your `on_cell_value_changed` handler to ensure data integrity.

pcweb/components/docpage/sidebar/sidebar_items/enterprise.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ def get_sidebar_items_enterprise_components():
6565
names="Theme",
6666
link=enterprise.ag_grid.theme.path,
6767
),
68+
SideBarItem(
69+
names="Cell Selection",
70+
link=enterprise.ag_grid.cell_selection.path,
71+
),
6872
SideBarItem(
6973
names="Value Transformers",
7074
link=enterprise.ag_grid.value_transformers.path,

0 commit comments

Comments
 (0)