# Events > Cell events, header events, structural changes, and drag/drop callbacks. --- .. llms_copy::references/events .. toc:: ### Overview Dash Glide Grid provides comprehensive event callbacks for user interactions. Respond to clicks, hovers, structural changes, and drag/drop operations. ### Cell Events Track cell clicks, double-clicks, right-clicks, and hover states. Use `cellClicked` for navigation, `cellActivated` for drill-down actions. .. exec::examples.reference.events.cell_events :code: false ```python # File: examples/reference/events/cell_events.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "Product", "id": "product", "width": 150}, {"title": "Category", "id": "category", "width": 120}, {"title": "Price", "id": "price", "width": 100}, ] data = [ {"product": "Laptop", "category": "Electronics", "price": 999}, {"product": "Headphones", "category": "Electronics", "price": 149}, {"product": "Desk Chair", "category": "Furniture", "price": 299}, {"product": "Coffee Mug", "category": "Kitchen", "price": 15}, ] component = dmc.Stack([ dgg.GlideGrid( id={"type": "glide-grid", "index": "events-cell"}, columns=columns, data=data, height=180, rowMarkers="number", ), dmc.Paper( dmc.SimpleGrid( cols=2, spacing="xs", children=[ dmc.Stack([ dmc.Text("Cell Clicked", size="sm", fw=500), dmc.Code(id="cell-click-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Cell Activated (Enter/dbl-click)", size="sm", fw=500), dmc.Code(id="cell-activate-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Context Menu (right-click)", size="sm", fw=500), dmc.Code(id="cell-context-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Item Hovered", size="sm", fw=500), dmc.Code(id="cell-hover-output", block=True), ], gap="xs"), ], ), p="md", withBorder=True, ), ], gap="md") @callback( Output("cell-click-output", "children"), Input({"type": "glide-grid", "index": "events-cell"}, "cellClicked"), ) def on_cell_click(clicked): if clicked: return f'{{"col": {clicked["col"]}, "row": {clicked["row"]}}}' return "Click a cell..." @callback( Output("cell-activate-output", "children"), Input({"type": "glide-grid", "index": "events-cell"}, "cellActivated"), ) def on_cell_activate(activated): if activated: return f'{{"col": {activated["col"]}, "row": {activated["row"]}}}' return "Press Enter or double-click..." @callback( Output("cell-context-output", "children"), Input({"type": "glide-grid", "index": "events-cell"}, "cellContextMenu"), ) def on_context(event): if event: return f'{{"col": {event["col"]}, "row": {event["row"]}}}' return "Right-click a cell..." @callback( Output("cell-hover-output", "children"), Input({"type": "glide-grid", "index": "events-cell"}, "itemHovered"), ) def on_hover(item): if item and item.get("kind"): col = item.get("col", "-") row = item.get("row", "-") return f'{{"kind": "{item["kind"]}", "col": {col}, "row": {row}}}' return "Hover over grid..." ``` :defaultExpanded: false :withExpandedButton: true ### Header Events Respond to header clicks for sorting, menu interactions, and group header actions. Enable menus with `hasMenu` on columns. .. exec::examples.reference.events.header_events :code: false ```python # File: examples/reference/events/header_events.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "Name", "id": "name", "width": 140, "hasMenu": True, "group": "Person"}, {"title": "Email", "id": "email", "width": 180, "hasMenu": True, "group": "Person"}, {"title": "Department", "id": "dept", "width": 120, "group": "Work"}, {"title": "Status", "id": "status", "width": 100, "group": "Work"}, ] data = [ {"name": "Alice Chen", "email": "alice@example.com", "dept": "Engineering", "status": "Active"}, {"name": "Bob Miller", "email": "bob@example.com", "dept": "Design", "status": "Active"}, {"name": "Carol Davis", "email": "carol@example.com", "dept": "Marketing", "status": "Away"}, ] component = dmc.Stack([ dmc.Text("Click headers, menu icons, or group headers to see events.", size="sm", c="dimmed"), dgg.GlideGrid( id={"type": "glide-grid", "index": "events-header"}, columns=columns, data=data, height=160, groupHeaderHeight=28, ), dmc.Paper( dmc.SimpleGrid( cols=2, spacing="xs", children=[ dmc.Stack([ dmc.Text("Header Clicked", size="sm", fw=500), dmc.Code(id="header-click-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Header Menu Clicked", size="sm", fw=500), dmc.Code(id="header-menu-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Group Header Clicked", size="sm", fw=500), dmc.Code(id="group-header-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Header Context Menu", size="sm", fw=500), dmc.Code(id="header-context-output", block=True), ], gap="xs"), ], ), p="md", withBorder=True, ), ], gap="md") @callback( Output("header-click-output", "children"), Input({"type": "glide-grid", "index": "events-header"}, "headerClicked"), ) def on_header_click(clicked): if clicked: return f'{{"col": {clicked["col"]}}}' return "Click a column header..." @callback( Output("header-menu-output", "children"), Input({"type": "glide-grid", "index": "events-header"}, "headerMenuClicked"), ) def on_header_menu(clicked): if clicked: return f'{{"col": {clicked["col"]}, "screenX": {clicked["screenX"]}, "screenY": {clicked["screenY"]}}}' return "Click menu icon..." @callback( Output("group-header-output", "children"), Input({"type": "glide-grid", "index": "events-header"}, "groupHeaderClicked"), ) def on_group_header(clicked): if clicked: return f'{{"col": {clicked["col"]}, "group": "{clicked["group"]}"}}' return "Click group header..." @callback( Output("header-context-output", "children"), Input({"type": "glide-grid", "index": "events-header"}, "headerContextMenu"), ) def on_header_context(event): if event: return f'{{"col": {event["col"]}}}' return "Right-click header..." ``` :defaultExpanded: false :withExpandedButton: true ### Structural Events Track column and row reordering with `columnMoved` and `rowMoved`. Monitor column resizing with `columnWidths`. .. exec::examples.reference.events.structural_events :code: false ```python # File: examples/reference/events/structural_events.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output, State columns = [ {"title": "Task", "id": "task", "width": 150}, {"title": "Priority", "id": "priority", "width": 100}, {"title": "Due Date", "id": "due", "width": 110}, ] data = [ {"task": "Review PRs", "priority": "High", "due": "2024-01-15"}, {"task": "Update docs", "priority": "Medium", "due": "2024-01-18"}, {"task": "Team standup", "priority": "Low", "due": "2024-01-20"}, {"task": "Deploy v2.0", "priority": "High", "due": "2024-01-22"}, ] component = dmc.Stack([ dmc.Text("Drag columns or rows to reorder. Resize columns by dragging edges.", size="sm", c="dimmed"), dgg.GlideGrid( id={"type": "glide-grid", "index": "events-structural"}, columns=columns, data=data, height=180, rowMarkers="number", columnMovable=True, rowMovable=True, columnResize=True, ), dmc.Paper( dmc.SimpleGrid( cols=3, spacing="xs", children=[ dmc.Stack([ dmc.Text("Column Moved", size="sm", fw=500), dmc.Code(id="col-moved-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Row Moved", size="sm", fw=500), dmc.Code(id="row-moved-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Column Widths", size="sm", fw=500), dmc.Code(id="col-widths-output", block=True), ], gap="xs"), ], ), p="md", withBorder=True, ), ], gap="md") @callback( Output({"type": "glide-grid", "index": "events-structural"}, "columns"), Output("col-moved-output", "children"), Input({"type": "glide-grid", "index": "events-structural"}, "columnMoved"), State({"type": "glide-grid", "index": "events-structural"}, "columns"), prevent_initial_call=True, ) def on_col_moved(moved, current_columns): if not moved: return current_columns, "Drag a column header..." start_idx, end_idx = moved["startIndex"], moved["endIndex"] new_columns = current_columns.copy() new_columns.insert(end_idx, new_columns.pop(start_idx)) return new_columns, f'{{"from": {start_idx}, "to": {end_idx}}}' @callback( Output({"type": "glide-grid", "index": "events-structural"}, "data"), Output("row-moved-output", "children"), Input({"type": "glide-grid", "index": "events-structural"}, "rowMoved"), State({"type": "glide-grid", "index": "events-structural"}, "data"), prevent_initial_call=True, ) def on_row_moved(moved, current_data): if not moved: return current_data, "Drag a row marker..." start_idx, end_idx = moved["startIndex"], moved["endIndex"] new_data = current_data.copy() new_data.insert(end_idx, new_data.pop(start_idx)) return new_data, f'{{"from": {start_idx}, "to": {end_idx}}}' @callback( Output("col-widths-output", "children"), Input({"type": "glide-grid", "index": "events-structural"}, "columnWidths"), ) def on_col_widths(widths): if widths: return str(widths) return "Resize a column..." ``` :defaultExpanded: false :withExpandedButton: true ### Drag & Drop Enable external drag operations with `isDraggable`. Track drag start, drag over, and drop events for custom drag-and-drop workflows. .. exec::examples.reference.events.drag_drop :code: false ```python # File: examples/reference/events/drag_drop.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output columns = [ {"title": "Item", "id": "item", "width": 150}, {"title": "Location", "id": "location", "width": 120}, {"title": "Quantity", "id": "qty", "width": 80}, ] data = [ {"item": "Widget A", "location": "Warehouse 1", "qty": 100}, {"item": "Widget B", "location": "Warehouse 2", "qty": 250}, {"item": "Gadget X", "location": "Warehouse 1", "qty": 75}, ] component = dmc.Stack([ dmc.Text("Enable isDraggable to track drag events. Drag files onto the grid to see drop events.", size="sm", c="dimmed"), dgg.GlideGrid( id={"type": "glide-grid", "index": "events-drag"}, columns=columns, data=data, height=160, isDraggable="cell", ), dmc.Paper( dmc.SimpleGrid( cols=3, spacing="xs", children=[ dmc.Stack([ dmc.Text("Drag Started", size="sm", fw=500), dmc.Code(id="drag-start-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Drag Over Cell", size="sm", fw=500), dmc.Code(id="drag-over-output", block=True), ], gap="xs"), dmc.Stack([ dmc.Text("Dropped On Cell", size="sm", fw=500), dmc.Code(id="drop-output", block=True), ], gap="xs"), ], ), p="md", withBorder=True, ), ], gap="md") @callback( Output("drag-start-output", "children"), Input({"type": "glide-grid", "index": "events-drag"}, "dragStarted"), ) def on_drag_start(event): if event: return f'{{"col": {event["col"]}, "row": {event["row"]}}}' return "Start dragging a cell..." @callback( Output("drag-over-output", "children"), Input({"type": "glide-grid", "index": "events-drag"}, "dragOverCell"), ) def on_drag_over(event): if event: return f'{{"col": {event["col"]}, "row": {event["row"]}}}' return "Drag over grid..." @callback( Output("drop-output", "children"), Input({"type": "glide-grid", "index": "events-drag"}, "droppedOnCell"), ) def on_drop(event): if event: return f'{{"col": {event["col"]}, "row": {event["row"]}}}' return "Drop on grid..." ``` :defaultExpanded: false :withExpandedButton: true ### Viewport Events Monitor the visible region and track total click counts. Useful for lazy loading and analytics. .. exec::examples.reference.events.viewport :code: false ```python # File: examples/reference/events/viewport.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output # Generate more data to enable scrolling columns = [ {"title": "ID", "id": "id", "width": 60}, {"title": "Name", "id": "name", "width": 140}, {"title": "Value", "id": "value", "width": 100}, {"title": "Status", "id": "status", "width": 100}, ] data = [ {"id": i, "name": f"Item {i}", "value": i * 10, "status": "Active" if i % 2 == 0 else "Pending"} for i in range(1, 51) ] component = dmc.Stack([ dmc.Text("Scroll the grid to see visible region changes.", size="sm", c="dimmed"), dgg.GlideGrid( id={"type": "glide-grid", "index": "events-viewport"}, columns=columns, data=data, height=200, rowMarkers="number", ), dmc.Paper( dmc.Stack([ dmc.Text("Visible Region", size="sm", fw=500), dmc.Code(id="viewport-output", block=True), dmc.Text("Click Counter", size="sm", fw=500, mt="xs"), dmc.Code(id="clicks-output", block=True), ], gap="xs"), p="md", withBorder=True, ), ], gap="md") @callback( Output("viewport-output", "children"), Input({"type": "glide-grid", "index": "events-viewport"}, "visibleRegion"), ) def on_visible_region(region): if region: return ( f'{{"x": {region["x"]}, "y": {region["y"]}, ' f'"width": {region["width"]}, "height": {region["height"]}}}' ) return "Scroll to update..." @callback( Output("clicks-output", "children"), Input({"type": "glide-grid", "index": "events-viewport"}, "nClicks"), ) def on_clicks(n): return f"Total clicks: {n or 0}" ``` :defaultExpanded: false :withExpandedButton: true ### Props Reference #### Cell Event Props | Property | Type | Description | |----------|------|-------------| | `cellClicked` | dict | Last clicked cell: `{col, row, timestamp}` | | `cellActivated` | dict | Last activated cell (Enter/Space/double-click): `{col, row, timestamp}` | | `cellContextMenu` | dict | Last right-clicked cell: `{col, row, timestamp}` | | `itemHovered` | dict | Currently hovered item: `{col, row, kind, timestamp}` | | `nClicks` | number | Total cell click count | #### Header Event Props | Property | Type | Description | |----------|------|-------------| | `headerClicked` | dict | Last clicked header: `{col, timestamp}` | | `headerContextMenu` | dict | Last right-clicked header: `{col, timestamp}` | | `headerMenuClicked` | dict | Menu icon clicked: `{col, screenX, screenY, timestamp}` | | `headerMenuItemClicked` | dict | Custom menu item clicked: `{col, itemId, timestamp}` | | `groupHeaderClicked` | dict | Group header clicked: `{col, group, timestamp}` | #### Structural Event Props | Property | Type | Description | |----------|------|-------------| | `columnMoved` | dict | Column drag-reorder: `{startIndex, endIndex, timestamp}` | | `rowMoved` | dict | Row drag-reorder: `{startIndex, endIndex, timestamp}` | | `columnWidths` | list | Current widths after resize: `[100, 150, 200]` | #### Drag & Drop Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `isDraggable` | bool/string | - | Enable dragging: `True`, `"header"`, or `"cell"` | | `dragStarted` | dict | - | Drag began: `{col, row, timestamp}` | | `dragOverCell` | dict | - | External drag over cell: `{col, row, timestamp}` | | `droppedOnCell` | dict | - | External drop on cell: `{col, row, timestamp}` | #### Viewport Props | Property | Type | Description | |----------|------|-------------| | `visibleRegion` | dict | Visible area: `{x, y, width, height, tx, ty}` | --- *Source: /reference/events* *Generated with dash-improve-my-llms*