R

ReflexKR

Reflex-Dokumentation

Die Komponentenwerkstatt: Reflex' 100 Bibliotheksbausteine

·

Kursüberblick

Layout

·

Box

·

Flex

·

Stack

·

Grid

·

Container

·

Section

·

Center

·

Spacer

·

Separator

·

Card

·

Inset

·

Aspect Ratio

·

Fragment

Typografie

·

Text

·

Heading

·

Link

·

Code

·

Markdown

·

Blockquote

·

Quote

·

Strong

·

Em

·

Kbd

Formulare

·

Button

·

Input

·

Text Area

·

Checkbox

·

Switch

·

Radio Group

·

Select

·

Slider

·

Form

·

Upload

Datenanzeige

·

Badge

·

Avatar

·

Icon

·

Callout

·

List

·

Data List

·

Code Block

·

Progress

·

Spinner

·

Scroll Area

·

Moment

Auf- und Zuklappen

·

Tabs

·

Accordion

·

Segmented Control

Overlays

·

Tooltip

·

Popover

·

Hover Card

·

Dialog

·

Alert Dialog

·

Drawer

·

Dropdown Menu

·

Context Menu

·

Toast

Dynamisches Rendern

·

Cond

·

Match

·

Foreach

·

Auto Scroll

Medien

·

Image

·

Audio

·

Video

Tabellen und Datengrids

·

Table

·

Data Table

·

Data Editor

Diagramme

·

Area Chart

·

Bar Chart

·

Line Chart

·

Composed Chart

·

Pie Chart

·

Radar Chart

·

Radial Bar Chart

·

Scatter Chart

·

Funnel Chart

·

Treemap

·

Sankey Chart

·

Error Bar

Diagrammbausteine

·

Axis

·

Cartesian Grid

·

Chart Tooltip

·

Legend

·

Label

·

Reference

·

Brush

Andere Diagrammbibliotheken

·

Plotly

·

Pyplot

HTML-Elemente

·

HTML

·

HTML Text

·

HTML Layout

·

HTML Forms

·

HTML Media

·

HTML Tables

·

SVG

Weitere Werkzeuge

·

Theme

·

Skeleton

·

Clipboard

·

Html Embed

·

Script

·

Memo

Die Komponentenwerkstatt: Reflex' 100 Bibliotheksbausteine
Tabellen und Datengrids

Data Editor

rx.data_editorrx.data_editor_theme

Offizielle Doku

Werkstattauftrag

Mach die Bestandsliste des Cafés wie in Excel direkt per Klick in die Zellen bearbeitbar, und lass bei jeder Änderung den Gesamtwert des Bestands neu berechnen.

rx.data_editor ist ein Datenraster, in dem man wie in einer Tabellenkalkulation Zellen auswählt und bearbeitet. Gezeichnet wird es mit Glide Data Grid, daher bleibt es auch bei sehr vielen Zeilen und Spalten schnell. Für reine Lesetabellen reicht Data Table; diese Komponente nimmst du, wenn Nutzer Werte ändern sollen.

columns ist eine Liste mit einem dict pro Spalte.

  • title: die Spaltenüberschrift.
  • id: die id der Spalte. Fehlt sie, wird title in Kleinbuchstaben verwendet.
  • width: die Spaltenbreite (px).
  • type: die Art der Zelle: "str" (Standard), "int", "float", "bool" oder "image".
  • group: zeichnet über allen Spalten mit demselben Wert eine zusätzliche Gruppenüberschrift.

data ist eine Liste mit einer Liste pro Zeile. Jeder Wert muss zum type seiner Spalte passen.

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],
    ],
)

Props ausprobieren

Klicke in das Raster und wähle Zellen, Zeilen und Spalten aus. Ein Doppelklick auf eine Zelle öffnet das Bearbeitungsfeld (dieses Labor speichert keine Werte, geänderte Werte springen also gleich wieder zurück).

Props ausprobieren

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 ist die Markierung vor jeder Zeile (Nummer, Checkbox), *_select der auswählbare Bereich, show_search das Suchfeld oben.
PropWerteVerwendung
columns · dataListeSpalteneinstellungen, Zeilendaten
rowsGanzzahlZeilenanzahl. Fehlt sie, die Länge von data
row_height · header_height · group_header_heightGanzzahl (px)Höhe von Zeilen, Spaltenüberschriften und Gruppenüberschriften
row_markers"none" "number" "checkbox" "both" "checkbox-visible" "clickable-number"Markierung vor jeder Zeile
row_marker_start_index · row_marker_widthGanzzahlStartwert der Zeilennummern, Breite der Markierungsspalte
freeze_columnsGanzzahlAnzahl der Spalten, die beim horizontalen Scrollen links fixiert bleiben
min_column_width · max_column_width · max_column_auto_widthGanzzahl (px)Grenzen der Spaltenbreite
column_select · row_select"none" "single" "multi"Spalten bzw. Zeilen auswählen
range_select"none" "cell" "rect" "multi-cell" "multi-rect"Zellbereiche auswählen
*_selection_blending · row_selection_mode · span_range_behaviorStringFeinheiten, etwa ob verschiedene Auswahlarten gleichzeitig bestehen dürfen
smooth_scroll_x · smooth_scroll_yTrue / FalseWeiches Scrollen
vertical_border · draw_focus_ring · fixed_shadow_x · fixed_shadow_yTrue / FalseSenkrechte Linien, Fokusrahmen, Schatten der fixierten Bereiche
fill_handleTrue / FalseGriff an der Zellecke, mit dem man Werte durch Ziehen auffüllt
get_cells_for_selectionTrue / FalseAusgewählte Zellen kopierbar machen (Standard True)
overscroll_x · overscroll_y · scroll_offset_x · scroll_offset_yGanzzahlScrollspielraum über das Ende hinaus, anfängliche Scrollposition
prevent_diagonal_scrolling · show_searchTrue / FalseDiagonales Scrollen verhindern, Suchfeld
themerx.data_editor_theme(...) oder dictFarben und Schriften
grid_selectionAuswahl-dictAktuelle Auswahl. Wer on_grid_selection_change nutzt, muss es unbedingt mit anbinden
EventÜbergebene WerteWann
on_cell_clicked · on_cell_activated · on_cell_context_menu[Spalte, Zeile]Klick auf eine Zelle, Aktivierung per Enter oder Doppelklick, Rechtsklick
on_cell_edited[Spalte, Zeile], neues Zell-dictWenn ein Zellwert geändert wurde (der neue Wert steht in dict["data"])
on_finished_editingneues Zell-dict, BewegungsrichtungWenn sich das Bearbeitungsfeld schließt
on_header_clicked · on_header_context_menu[Spalte, Zeile]Klick bzw. Rechtsklick auf eine Spaltenüberschrift
on_header_menu_clickSpalte, PositionKlick auf den Menü-Button einer Spaltenüberschrift
on_group_header_clicked · on_group_header_context_menu · on_group_header_renamed-Klick, Rechtsklick bzw. Umbenennen einer Gruppenüberschrift
on_item_hovered[Spalte, Zeile]Wenn die Maus über eine Zelle fährt
on_grid_selection_change · on_selection_clearedAuswahl-dict · -Wenn sich die Auswahl ändert bzw. aufgehoben wird
on_deleteAuswahl-dictWenn in ausgewählten Zellen die Entf-Taste gedrückt wird
on_row_appended · on_column_resize · on_search_close- · Spalte, Breite · -Zeile angefügt, Spaltenbreite geändert, Suchfeld geschlossen

Bildzellen

Eine Spalte mit type="image" zeigt Bildadressen als kleine Vorschaubilder. Der Wert kann eine einzelne Adresse sein oder eine Liste von Adressen mit mehreren Bildern. Damit die Bilder gut zu sehen sind, erhöhst du row_height. Ein Klick auf eine Bildzelle öffnet eine vergrößerte Ansicht.

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",
)

Klick auf eine Zelle: on_cell_clicked

on_cell_clicked übergibt die Position der angeklickten Zelle als [Spalte, Zeile] (beide ab 0 gezählt). Die Spalteneinstellungen unten enthalten group: "Data", daher steht über den fünf Spalten außer Title zusätzlich eine Gruppenüberschrift „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%",
)

Geänderte Werte speichern: on_cell_edited

Der Data Editor macht Zellen nur bearbeitbar, speichert geänderte Werte aber nicht von selbst. Erst wenn der Handler für on_cell_edited Position und neue Zellinfo entgegennimmt und data im State ändert, bleibt die Änderung sichtbar. Der neue Wert steht in new_value["data"]. Ändere einen Wert per Doppelklick oder klicke auf eine Checkbox in Activated.

Die offizielle Doku zeigt für dieses Event kein Beispiel, doch für ein bearbeitbares Raster ist es unverzichtbar.

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%",
)

Gestalten: theme

An theme übergibst du Farben und Schriften, entweder als Keyword-Argumente an rx.data_editor_theme(...) (in der offiziellen Doku from reflex.components.datadisplay.dataeditor import DataEditorTheme) oder direkt als dict. Die Schlüssel funktionieren sowohl mit Unterstrichen wie accent_color als auch in camelCase wie accentColor. Unten kommen zu einem dunklen Theme noch row_height=50, weiches Scrollen und die Auswahl einzelner Spalten hinzu.

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",
)

Auftrag erledigt

Die Bestandsliste wird über on_cell_edited gespeichert, Gesamtwert und Zahl der Nachbestellungen sind berechnete Variablen. Ändert man Menge oder Stückpreis, aktualisieren sich die Badges darunter sofort. Die Artikelspalte bleibt mit freeze_columns=1 fixiert.

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%",
)

Werkstattnotizen

  • columns ist eine Liste von dicts {title, type, width, id, group}, data eine Liste von Zeilen. Die Werte passen zum type der Spalte.

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

  • Geänderte Werte bleiben nur, wenn on_cell_edited((Spalte, Zeile), neue Zelle) data im State ändert.

  • Auswahlbereiche über column_select · row_select · range_select, Zeilenmarkierung über row_markers.

  • theme=rx.data_editor_theme(...) oder dict; die Größe über height und row_height.

← Zurück

Tabellen und Datengrids · Data Table

Weiter →

Diagramme · Area Chart

Über neue Lektionen informiert werden

Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.

Erhoben: deine E-Mail-Adresse · Zweck: Hinweise auf neue Lektionen oder den Start dieses Kurses · Speicherdauer: bis du die Löschung verlangst. Keine andere Nutzung, keine Weitergabe. Antworte einfach auf eine Benachrichtigung, dann löschen wir sie sofort.

Fragen & Antworten

Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.

Wird als reiner Text angezeigt, ohne Links oder Formatierung.

R

ReflexKR

Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.

ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee

Hinweis zu Affiliate-Links
한국어English日本語简体中文EspañolDeutsch

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

Built with Reflex