R

ReflexKR

Documentación de Reflex

El taller de componentes: los 100 componentes de Reflex

·

Resumen del curso

Diseño

·

Box

·

Flex

·

Stack

·

Grid

·

Container

·

Section

·

Center

·

Spacer

·

Separator

·

Card

·

Inset

·

Aspect Ratio

·

Fragment

Tipografía

·

Text

·

Heading

·

Link

·

Code

·

Markdown

·

Blockquote

·

Quote

·

Strong

·

Em

·

Kbd

Formularios

·

Button

·

Input

·

Text Area

·

Checkbox

·

Switch

·

Radio Group

·

Select

·

Slider

·

Form

·

Upload

Visualización de datos

·

Badge

·

Avatar

·

Icon

·

Callout

·

List

·

Data List

·

Code Block

·

Progress

·

Spinner

·

Scroll Area

·

Moment

Mostrar y ocultar

·

Tabs

·

Accordion

·

Segmented Control

Superposiciones

·

Tooltip

·

Popover

·

Hover Card

·

Dialog

·

Alert Dialog

·

Drawer

·

Dropdown Menu

·

Context Menu

·

Toast

Renderizado dinámico

·

Cond

·

Match

·

Foreach

·

Auto Scroll

Multimedia

·

Image

·

Audio

·

Video

Tablas y cuadrículas de datos

·

Table

·

Data Table

·

Data Editor

Gráficos

·

Area Chart

·

Bar Chart

·

Line Chart

·

Composed Chart

·

Pie Chart

·

Radar Chart

·

Radial Bar Chart

·

Scatter Chart

·

Funnel Chart

·

Treemap

·

Sankey Chart

·

Error Bar

Piezas de gráficos

·

Axis

·

Cartesian Grid

·

Chart Tooltip

·

Legend

·

Label

·

Reference

·

Brush

Otras bibliotecas de gráficos

·

Plotly

·

Pyplot

Elementos HTML

·

HTML

·

HTML Text

·

HTML Layout

·

HTML Forms

·

HTML Media

·

HTML Tables

·

SVG

Otras herramientas

·

Theme

·

Skeleton

·

Clipboard

·

Html Embed

·

Script

·

Memo

El taller de componentes: los 100 componentes de Reflex
Tablas y cuadrículas de datos

Data Editor

rx.data_editorrx.data_editor_theme

Documentación oficial

Pedido del taller

Haz que la tabla de existencias de la cafetería se pueda editar pulsando directamente en las celdas, como en Excel, y que el valor total del inventario se recalcule con cada cambio.

rx.data_editor es una cuadrícula de datos en la que, como en una hoja de cálculo, se eligen celdas y se editan. Se dibuja con Glide Data Grid, así que va rápida aunque tenga muchísimas filas y columnas. Para una tabla de solo lectura basta con Data Table; este componente es para cuando el usuario tiene que modificar valores.

columns es una lista con un dict por columna.

  • title: el título de la columna.
  • id: el id de la columna. Si falta, es el title en minúsculas.
  • width: el ancho de la columna (px).
  • type: el tipo de celda. Se usan "str" (por defecto), "int", "float", "bool" e "image".
  • group: dibuja un título de grupo extra sobre las columnas que comparten ese valor.

data es una lista con una lista por fila. Cada valor debe coincidir con el type de su columna.

rx.data_editor(
    columns=[
        {"title": "Code", "type": "str"},
        {"title": "Value", "type": "int"},
        {"title": "Activated", "type": "bool"},
    ],
    data=[
        ["A", 1, True],
        ["B", 2, False],
        ["C", 3, False],
        ["D", 4, True],
        ["E", 5, True],
        ["F", 6, False],
    ],
)

Prueba las propiedades

Pulsa en la cuadrícula para seleccionar celdas, filas y columnas. Con doble clic en una celda se abre el editor (este banco de pruebas no guarda los valores, así que lo editado vuelve enseguida a su valor original).

Prueba las propiedades

row_markers

column_select

row_select

range_select

vertical_border

show_search

rx.data_editor(
    columns=[
        {"title": "Code", "type": "str"},
        {"title": "Value", "type": "int"},
        {"title": "Activated", "type": "bool"},
    ],
    data=[["A", 1, True], ["B", 2, False], ["C", 3, False], ["D", 4, True]],
    row_markers="number",
    column_select="single",
    row_select="multi",
    range_select="rect",
    vertical_border=True,
    show_search=False,
    height="220px",
)
row_markers es la marca delante de cada fila (número o casilla), *_select lo que se puede seleccionar y show_search la búsqueda de la parte superior.
PropiedadValoresUso
columns · dataListaConfiguración de columnas, datos de las filas
rowsEnteroNúmero de filas. Si falta, la longitud de data
row_height · header_height · group_header_heightEntero (px)Alto de las filas, de los títulos de columna y de los títulos de grupo
row_markers"none" "number" "checkbox" "both" "checkbox-visible" "clickable-number"Marca delante de cada fila
row_marker_start_index · row_marker_widthEnteroNúmero inicial de fila, ancho de la columna de marcas
freeze_columnsEnteroColumnas fijas a la izquierda al hacer scroll horizontal
min_column_width · max_column_width · max_column_auto_widthEntero (px)Límites del ancho de columna
column_select · row_select"none" "single" "multi"Selección de columnas y filas
range_select"none" "cell" "rect" "multi-cell" "multi-rect"Selección de rangos de celdas
*_selection_blending · row_selection_mode · span_range_behaviorCadenaDetalles como si se combinan varios tipos de selección
smooth_scroll_x · smooth_scroll_yTrue / FalseScroll suave
vertical_border · draw_focus_ring · fixed_shadow_x · fixed_shadow_yTrue / FalseLíneas verticales, borde de foco, sombra de las zonas fijas
fill_handleTrue / FalseAsa en la esquina de la celda para rellenar valores arrastrando
get_cells_for_selectionTrue / FalsePermitir copiar las celdas seleccionadas (True por defecto)
overscroll_x · overscroll_y · scroll_offset_x · scroll_offset_yEnteroMargen de scroll más allá del final, posición de scroll inicial
prevent_diagonal_scrolling · show_searchTrue / FalseImpedir el scroll en diagonal, búsqueda
themerx.data_editor_theme(...) o dictColores y tipografía
grid_selectiondict de selecciónSelección actual. Si usas on_grid_selection_change, conéctalos siempre juntos
EventoRecibeCuándo
on_cell_clicked · on_cell_activated · on_cell_context_menu[columna, fila]Al pulsar una celda, al activarla con Enter o doble clic, al hacer clic derecho
on_cell_edited[columna, fila], dict de la nueva celdaAl editar el valor de una celda (el nuevo valor está en dict["data"])
on_finished_editingdict de la nueva celda, dirección de avanceAl cerrarse el editor
on_header_clicked · on_header_context_menu[columna, fila]Al pulsar un título de columna, al hacer clic derecho en él
on_header_menu_clickColumna, posiciónAl pulsar el botón de menú de un título de columna
on_group_header_clicked · on_group_header_context_menu · on_group_header_renamed-Al pulsar un título de grupo, al hacer clic derecho en él, al renombrarlo
on_item_hovered[columna, fila]Cuando el ratón pasa por encima de una celda
on_grid_selection_change · on_selection_cleareddict de selección · -Cuando la selección cambia o se borra
on_deletedict de selecciónAl pulsar la tecla Supr en las celdas seleccionadas
on_row_appended · on_column_resize · on_search_close- · columna, ancho · -Añadir una fila, cambiar el ancho de una columna, cerrar la búsqueda

Celdas de imagen

Las columnas con type="image" muestran la dirección de una imagen como una miniatura. El valor puede ser una sola dirección o una lista de direcciones con varias imágenes. Sube row_height para que se vean bien. Al pulsar una celda de imagen se abre una ventana para verla en grande.

rx.data_editor(
    columns=[
        {"title": "Preview", "type": "image", "width": 120},
        {"title": "Name", "type": "str"},
    ],
    data=[
        ["https://picsum.photos/id/237/160/100", "Puppy"],
        ["https://picsum.photos/id/1025/160/100", "Pug"],
        [["https://picsum.photos/id/1084/160/100", "https://picsum.photos/id/1074/160/100"], "Two animals"],
    ],
    row_height=90,
    height="320px",
)

Al pulsar una celda: on_cell_clicked

on_cell_clicked pasa la posición de la celda pulsada como [columna, fila] (ambas empiezan en 0). La configuración de columnas de abajo tiene group: "Data", así que sobre las cinco columnas que no son Title aparece un título de grupo extra, «Data».

Cell clicked:

from typing import Any


class DataEditorClickState(rx.State):
    clicked_data: str = "Cell clicked: "
    cols: list[dict[str, Any]] = [
        {"title": "Title", "type": "str"},
        {"title": "Name", "type": "str", "group": "Data", "width": 220},
        {"title": "Birth", "type": "str", "group": "Data", "width": 150},
        {"title": "Human", "type": "bool", "group": "Data", "width": 80},
        {"title": "House", "type": "str", "group": "Data"},
        {"title": "Patronus", "type": "str", "group": "Data"},
    ]
    data: list[list[Any]] = [
        ["1", "Harry James Potter", "31 July 1980", True, "Gryffindor", "Stag"],
        ["2", "Ronald Bilius Weasley", "1 March 1980", True, "Gryffindor", "Jack Russell terrier"],
        ["3", "Hermione Jean Granger", "19 September 1979", True, "Gryffindor", "Otter"],
        ["4", "Rubeus Hagrid", "6 December 1928", False, "Gryffindor", "None"],
    ]

    @rx.event
    def click_cell(self, pos: tuple[int, int]):
        col, row = pos
        self.clicked_data = f"Cell clicked: column {col}, row {row}"


rx.vstack(
    rx.heading(DataEditorClickState.clicked_data, size="3"),
    rx.data_editor(
        columns=DataEditorClickState.cols,
        data=DataEditorClickState.data,
        on_cell_clicked=DataEditorClickState.click_cell,
        height="220px",
    ),
    width="100%",
)

Guardar lo editado: on_cell_edited

Data Editor solo permite editar las celdas; no guarda lo editado por sí mismo. Para que el cambio quede en pantalla, el handler de on_cell_edited tiene que recibir la posición y la información de la nueva celda y modificar el data del State. El nuevo valor está en new_value["data"]. Edita un valor con doble clic en una celda o pulsa la casilla de Activated.

La documentación oficial no trae ejemplo de este evento, pero es imprescindible para hacer una cuadrícula editable.

Last edit: nothing yet

from typing import Any


class DataEditorEditState(rx.State):
    cols: list[dict[str, Any]] = [
        {"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]]
    last_edit: str = "nothing yet"

    @rx.event
    def edit_cell(self, pos: tuple[int, int], new_value: dict[str, Any]):
        col, row = pos
        rows = [list(r) for r in self.data]
        rows[row][col] = new_value.get("data")
        self.data = rows
        self.last_edit = f"row {row}, column {col} -> {new_value.get('data')}"

    @rx.event
    def add_row(self):
        self.data = self.data + [["New", 0, False]]


rx.vstack(
    rx.data_editor(
        columns=DataEditorEditState.cols,
        data=DataEditorEditState.data,
        on_cell_edited=DataEditorEditState.edit_cell,
        row_markers="number",
        height="200px",
    ),
    rx.hstack(
        rx.button("Add row", size="1", on_click=DataEditorEditState.add_row),
        rx.text("Last edit: ", DataEditorEditState.last_edit, size="2"),
        align="center",
    ),
    width="100%",
)

Estilo: theme

En theme van los colores y la tipografía. Pasa argumentos con nombre a rx.data_editor_theme(...) (en la documentación oficial, from reflex.components.datadisplay.dataeditor import DataEditorTheme) o pasa directamente un dict. Las claves valen tanto con guiones bajos, como accent_color, como en camelCase, como accentColor. Abajo, un tema oscuro con row_height=50, scroll suave y selección de una columna cada vez.

dataeditor_dark_theme = {
    "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",
}


rx.data_editor(
    columns=[
        {"title": "Code", "type": "str", "width": 120},
        {"title": "Value", "type": "int", "width": 120},
        {"title": "Activated", "type": "bool", "width": 120},
    ],
    data=[["A", 1, True], ["B", 2, False], ["C", 3, False], ["D", 4, True], ["E", 5, True]],
    row_height=50,
    smooth_scroll_x=True,
    smooth_scroll_y=True,
    column_select="single",
    theme=rx.data_editor_theme(**dataeditor_dark_theme),
    height="260px",
)

Completar el pedido

La tabla de existencias guarda los cambios con on_cell_edited, y el valor total del inventario y el número de productos que hay que volver a pedir son variables calculadas. Al cambiar una cantidad o un precio unitario, los badges de abajo cambian al momento. La columna de artículos se fija con freeze_columns=1.

Stock value: $263.60To reorder: 1
from typing import Any


class DataEditorStockState(rx.State):
    cols: list[dict[str, Any]] = [
        {"title": "Item", "type": "str", "width": 160},
        {"title": "Qty", "type": "int", "width": 80},
        {"title": "Unit price", "type": "float", "width": 110},
        {"title": "Reorder", "type": "bool", "width": 90},
    ]
    data: list[list[Any]] = [
        ["Coffee beans", 12, 18.5, False],
        ["Paper cups", 300, 0.1, False],
        ["Oat milk", 4, 2.9, True],
    ]

    @rx.event
    def edit_cell(self, pos: tuple[int, int], new_value: dict[str, Any]):
        col, row = pos
        rows = [list(r) for r in self.data]
        rows[row][col] = new_value.get("data")
        self.data = rows

    @rx.var
    def total(self) -> str:
        value = sum(float(r[1] or 0) * float(r[2] or 0) for r in self.data)
        return f"${value:,.2f}"

    @rx.var
    def reorder_count(self) -> int:
        return sum(1 for r in self.data if r[3])


rx.vstack(
    rx.data_editor(
        columns=DataEditorStockState.cols,
        data=DataEditorStockState.data,
        on_cell_edited=DataEditorStockState.edit_cell,
        row_markers="number",
        freeze_columns=1,
        height="180px",
    ),
    rx.hstack(
        rx.badge("Stock value: ", DataEditorStockState.total, size="2"),
        rx.badge("To reorder: ", DataEditorStockState.reorder_count, color_scheme="orange", size="2"),
    ),
    width="100%",
)

Notas del taller

  • columns es una lista de dicts {title, type, width, id, group}; data, una lista de filas. Los valores deben coincidir con el type de la columna.

  • type: str · int · float · bool · image.

  • Lo editado solo se conserva si on_cell_edited((columna, fila), nueva celda) modifica el data del State.

  • Qué se puede seleccionar: column_select · row_select · range_select; la marca delante de cada fila: row_markers.

  • theme=rx.data_editor_theme(...) o un dict; el tamaño, con height y row_height.

← Anterior

Tablas y cuadrículas de datos · Data Table

Siguiente →

Gráficos · Area Chart

Recibe avisos de nuevas lecciones

Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.

Datos: tu correo electrónico · Finalidad: avisos de nuevas lecciones o de la publicación de este curso · Conservación: hasta que pidas que lo borremos. No lo usamos para nada más ni lo compartimos. Responde a cualquier aviso y lo borraremos enseguida.

Preguntas y respuestas

Pregunta lo que quieras sobre esta lección. Aquí se reúnen las preguntas de todas las versiones de idioma de esta página.

Se muestra como texto plano, sin enlaces ni formato.

R

ReflexKR

Aprende Python y Reflex haciendo. Todos los ejemplos se ejecutaron y verificaron en Reflex 0.10.0.

ReflexKR es gratis y sin banners publicitarios. Si te ayudó, puedes apoyarlo con un café. ☕ Invítanos un café

Aviso de afiliados
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex