357 lines
10 KiB
Markdown
357 lines
10 KiB
Markdown
---
|
||
components:
|
||
- rx.data_editor
|
||
---
|
||
|
||
# Data Editor
|
||
|
||
A datagrid editor based on [Glide Data Grid](https://grid.glideapps.com/)
|
||
|
||
```python exec
|
||
import reflex as rx
|
||
from pcweb.pages.docs import library
|
||
from typing import Any
|
||
|
||
columns: list[dict[str, str]] = [
|
||
{
|
||
"title":"Code",
|
||
"type": "str",
|
||
},
|
||
{
|
||
"title":"Value",
|
||
"type": "int",
|
||
},
|
||
{
|
||
"title":"Activated",
|
||
"type": "bool",
|
||
},
|
||
]
|
||
data: list[list[Any]] = [
|
||
["A", 1, True],
|
||
["B", 2, False],
|
||
["C", 3, False],
|
||
["D", 4, True],
|
||
["E", 5, True],
|
||
["F", 6, False],
|
||
]
|
||
|
||
```
|
||
|
||
This component is introduced as an alternative to the [datatable]({library.datadisplay.datatable.path}) to support editing the displayed data.
|
||
|
||
## Columns
|
||
|
||
The columns definition should be a `list` of `dict`, each `dict` describing the associated columns.
|
||
Property of a column dict:
|
||
|
||
- `title`: The text to display in the header of the column.
|
||
- `id`: An id for the column, if not defined, will default to a lower case of `title`
|
||
- `width`: The width of the column.
|
||
- `type`: The type of the columns, default to `"str"`.
|
||
|
||
## Data
|
||
|
||
The `data` props of `rx.data_editor` accept a `list` of `list`, where each `list` represent a row of data to display in the table.
|
||
|
||
## Simple Example
|
||
|
||
Here is a basic example of using the data_editor representing data with no interaction and no styling. Below we define the `columns` and the `data` which are taken in by the `rx.data_editor` component. When we define the `columns` we must define a `title` and a `type` for each column we create. The columns in the `data` must then match the defined `type` or errors will be thrown.
|
||
|
||
```python demo box
|
||
rx.data_editor(
|
||
columns=columns,
|
||
data=data,
|
||
)
|
||
```
|
||
|
||
```python
|
||
columns: list[dict[str, str]] = [
|
||
{
|
||
"title":"Code",
|
||
"type": "str",
|
||
},
|
||
{
|
||
"title":"Value",
|
||
"type": "int",
|
||
},
|
||
{
|
||
"title":"Activated",
|
||
"type": "bool",
|
||
},
|
||
]
|
||
data: list[list[Any]] = [
|
||
["A", 1, True],
|
||
["B", 2, False],
|
||
["C", 3, False],
|
||
["D", 4, True],
|
||
["E", 5, True],
|
||
["F", 6, False],
|
||
]
|
||
```
|
||
|
||
```python
|
||
rx.data_editor(
|
||
columns=columns,
|
||
data=data,
|
||
)
|
||
```
|
||
|
||
## Interactive Example
|
||
|
||
```python exec
|
||
class DataEditorState_HP(rx.State):
|
||
|
||
clicked_data: str = "Cell clicked: "
|
||
cols: list[Any] = [
|
||
{"title": "Title", "type": "str"},
|
||
{
|
||
"title": "Name",
|
||
"type": "str",
|
||
"group": "Data",
|
||
"width": 300,
|
||
},
|
||
{
|
||
"title": "Birth",
|
||
"type": "str",
|
||
"id": "date",
|
||
"group": "Data",
|
||
"width": 150,
|
||
},
|
||
{
|
||
"title": "Human",
|
||
"type": "bool",
|
||
"group": "Data",
|
||
"width": 80,
|
||
},
|
||
{
|
||
"title": "House",
|
||
"type": "str",
|
||
"id": "date",
|
||
"group": "Data",
|
||
},
|
||
{
|
||
"title": "Wand",
|
||
"type": "str",
|
||
"id": "date",
|
||
"group": "Data",
|
||
"width": 250,
|
||
},
|
||
{
|
||
"title": "Patronus",
|
||
"type": "str",
|
||
"id": "date",
|
||
"group": "Data",
|
||
},
|
||
{
|
||
"title": "Blood status",
|
||
"type": "str",
|
||
"id": "date",
|
||
"group": "Data",
|
||
"width": 200,
|
||
}
|
||
]
|
||
|
||
data = [
|
||
["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "11' Holly phoenix feather", "Stag", "Half-blood"],
|
||
["2", "Ronald Bilius Weasley", "1 March 1980", True,"Gryffindor", "12' Ash unicorn tail hair", "Jack Russell terrier", "Pure-blood"],
|
||
["3", "Hermione Jean Granger", "19 September, 1979", True, "Gryffindor", "10¾' vine wood dragon heartstring", "Otter", "Muggle-born"],
|
||
["4", "Albus Percival Wulfric Brian Dumbledore", "Late August 1881", True, "Gryffindor", "15' Elder Thestral tail hair core", "Phoenix", "Half-blood"],
|
||
["5", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "16' Oak unknown core", "None", "Part-Human (Half-giant)"],
|
||
["6", "Fred Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"],
|
||
]
|
||
|
||
def click_cell(self, pos):
|
||
col, row = pos
|
||
yield self.get_clicked_data(pos)
|
||
|
||
|
||
def get_clicked_data(self, pos) -> str:
|
||
self.clicked_data = f"Cell clicked: {pos}"
|
||
|
||
```
|
||
|
||
Here we define a State, as shown below, that allows us to print the location of the cell as a heading when we click on it, using the `on_cell_clicked` `event trigger`. Check out all the other `event triggers` that you can use with datatable at the bottom of this page. We also define a `group` with a label `Data`. This groups all the columns with this `group` label under a larger group `Data` as seen in the table below.
|
||
|
||
```python demo box
|
||
rx.heading(DataEditorState_HP.clicked_data)
|
||
```
|
||
|
||
```python demo box
|
||
rx.data_editor(
|
||
columns=DataEditorState_HP.cols,
|
||
data=DataEditorState_HP.data,
|
||
on_cell_clicked=DataEditorState_HP.click_cell,
|
||
)
|
||
```
|
||
|
||
```python
|
||
class DataEditorState_HP(rx.State):
|
||
|
||
clicked_data: str = "Cell clicked: "
|
||
|
||
cols: list[Any] = [
|
||
{
|
||
"title": "Title",
|
||
"type": "str"
|
||
},
|
||
{
|
||
"title": "Name",
|
||
"type": "str",
|
||
"group": "Data",
|
||
"width": 300,
|
||
},
|
||
{
|
||
"title": "Birth",
|
||
"type": "str",
|
||
"group": "Data",
|
||
"width": 150,
|
||
},
|
||
{
|
||
"title": "Human",
|
||
"type": "bool",
|
||
"group": "Data",
|
||
"width": 80,
|
||
},
|
||
{
|
||
"title": "House",
|
||
"type": "str",
|
||
"group": "Data",
|
||
},
|
||
{
|
||
"title": "Wand",
|
||
"type": "str",
|
||
"group": "Data",
|
||
"width": 250,
|
||
},
|
||
{
|
||
"title": "Patronus",
|
||
"type": "str",
|
||
"group": "Data",
|
||
},
|
||
{
|
||
"title": "Blood status",
|
||
"type": "str",
|
||
"group": "Data",
|
||
"width": 200,
|
||
}
|
||
]
|
||
|
||
data = [
|
||
["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "11' Holly phoenix feather", "Stag", "Half-blood"],
|
||
["2", "Ronald Bilius Weasley", "1 March 1980", True,"Gryffindor", "12' Ash unicorn tail hair", "Jack Russell terrier", "Pure-blood"],
|
||
["3", "Hermione Jean Granger", "19 September, 1979", True, "Gryffindor", "10¾' vine wood dragon heartstring", "Otter", "Muggle-born"],
|
||
["4", "Albus Percival Wulfric Brian Dumbledore", "Late August 1881", True, "Gryffindor", "15' Elder Thestral tail hair core", "Phoenix", "Half-blood"],
|
||
["5", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "16' Oak unknown core", "None", "Part-Human (Half-giant)"],
|
||
["6", "Fred Weasley", "1 April, 1978", True, "Gryffindor", "Unknown", "Unknown", "Pure-blood"],
|
||
]
|
||
|
||
|
||
def click_cell(self, pos):
|
||
col, row = pos
|
||
yield self.get_clicked_data(pos)
|
||
|
||
|
||
def get_clicked_data(self, pos) -> str:
|
||
self.clicked_data = f"Cell clicked: \{pos}"
|
||
```
|
||
|
||
```python
|
||
rx.data_editor(
|
||
columns=DataEditorState_HP.cols,
|
||
data=DataEditorState_HP.data,
|
||
on_cell_clicked=DataEditorState_HP.click_cell,
|
||
)
|
||
```
|
||
|
||
## Styling Example
|
||
|
||
Now let's style our datatable to make it look more aesthetic and easier to use. We must first import `DataEditorTheme` and then we can start setting our style props as seen below in `dark_theme`.
|
||
|
||
We then set these themes using `theme=DataEditorTheme(**dark_theme)`. On top of the styling we can also set some `props` to make some other aesthetic changes to our datatable. We have set the `row_height` to equal `50` so that the content is easier to read. We have also made the `smooth_scroll_x` and `smooth_scroll_y` equal `True` so that we can smoothly scroll along the columns and rows. Finally, we added `column_select=single`, where column select can take any of the following values `none`, `single` or `multiple`.
|
||
|
||
```python exec
|
||
from reflex.components.datadisplay.dataeditor import DataEditorTheme
|
||
dark_theme = {
|
||
"accentColor": "#8c96ff",
|
||
"accentLight": "rgba(202, 206, 255, 0.253)",
|
||
"textDark": "#ffffff",
|
||
"textMedium": "#b8b8b8",
|
||
"textLight": "#a0a0a0",
|
||
"textBubble": "#ffffff",
|
||
"bgIconHeader": "#b8b8b8",
|
||
"fgIconHeader": "#000000",
|
||
"textHeader": "#a1a1a1",
|
||
"textHeaderSelected": "#000000",
|
||
"bgCell": "#16161b",
|
||
"bgCellMedium": "#202027",
|
||
"bgHeader": "#212121",
|
||
"bgHeaderHasFocus": "#474747",
|
||
"bgHeaderHovered": "#404040",
|
||
"bgBubble": "#212121",
|
||
"bgBubbleSelected": "#000000",
|
||
"bgSearchResult": "#423c24",
|
||
"borderColor": "rgba(225,225,225,0.2)",
|
||
"drilldownBorder": "rgba(225,225,225,0.4)",
|
||
"linkColor": "#4F5DFF",
|
||
"headerFontStyle": "bold 14px",
|
||
"baseFontStyle": "13px",
|
||
"fontFamily": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
|
||
}
|
||
```
|
||
|
||
```python demo box
|
||
rx.data_editor(
|
||
columns=DataEditorState_HP.cols,
|
||
data=DataEditorState_HP.data,
|
||
row_height=80,
|
||
smooth_scroll_x=True,
|
||
smooth_scroll_y=True,
|
||
column_select="single",
|
||
theme=DataEditorTheme(**dark_theme),
|
||
height="30vh",
|
||
)
|
||
```
|
||
|
||
```python
|
||
from reflex.components.datadisplay.dataeditor import DataEditorTheme
|
||
dark_theme_snake_case = {
|
||
"accent_color": "#8c96ff",
|
||
"accent_light": "rgba(202, 206, 255, 0.253)",
|
||
"text_dark": "#ffffff",
|
||
"text_medium": "#b8b8b8",
|
||
"text_light": "#a0a0a0",
|
||
"text_bubble": "#ffffff",
|
||
"bg_icon_header": "#b8b8b8",
|
||
"fg_icon_header": "#000000",
|
||
"text_header": "#a1a1a1",
|
||
"text_header_selected": "#000000",
|
||
"bg_cell": "#16161b",
|
||
"bg_cell_medium": "#202027",
|
||
"bg_header": "#212121",
|
||
"bg_header_has_focus": "#474747",
|
||
"bg_header_hovered": "#404040",
|
||
"bg_bubble": "#212121",
|
||
"bg_bubble_selected": "#000000",
|
||
"bg_search_result": "#423c24",
|
||
"border_color": "rgba(225,225,225,0.2)",
|
||
"drilldown_border": "rgba(225,225,225,0.4)",
|
||
"link_color": "#4F5DFF",
|
||
"header_font_style": "bold 14px",
|
||
"base_font_style": "13px",
|
||
"font_family": "Inter, Roboto, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, noto, arial, sans-serif",
|
||
}
|
||
```
|
||
|
||
```python
|
||
rx.data_editor(
|
||
columns=DataEditorState_HP.cols,
|
||
data=DataEditorState_HP.data,
|
||
row_height=80,
|
||
smooth_scroll_x=True,
|
||
smooth_scroll_y=True,
|
||
column_select="single",
|
||
theme=DataEditorTheme(**dark_theme),
|
||
height="30vh",
|
||
)
|
||
```
|