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
rx.dialog.rootrx.dialog.triggerrx.dialog.contentrx.dialog.titlerx.dialog.descriptionrx.dialog.closeOffizielle Doku
Werkstattauftrag
Klickt man auf der Mitgliedskarte auf „Profil bearbeiten“, soll in der Bildschirmmitte ein Fenster erscheinen, in dem man Name und E-Mail ändern und speichern kann.
rx.dialog ist ein modales Fenster in der Bildschirmmitte. Solange es offen ist, wird der Hintergrund abgedunkelt und lässt sich nicht anklicken, sodass sich der Nutzer ganz auf das Fenster konzentriert. Man nutzt es für kleine Aufgaben, die in einem Zug erledigt werden, etwa Daten bearbeiten oder einen neuen Eintrag anlegen. Es besteht aus sechs Teilen.
dialog.root: umschließt alle Teile des Dialogs.dialog.trigger: umschließt das Element, das den Dialog per Klick öffnet.dialog.content: der Inhalt des Fensters.dialog.title: der Titel des Fensters. Screenreader lesen ihn beim Öffnen vor.dialog.description: die Beschreibung des Fensters. Sie wird beim Öffnen mit vorgelesen.dialog.close: umschließt ein Element, das das Fenster per Klick schließt.rx.dialog.root(
rx.dialog.trigger(rx.button("Open Dialog")),
rx.dialog.content(
rx.dialog.title("Welcome to Reflex!"),
rx.dialog.description(
"This is a dialog component. You can render anything you want in here.",
),
rx.dialog.close(
rx.button("Close Dialog", size="3"),
),
),
)Die Fenstergröße bestimmen size (Innenabstand) und max_width (maximale Breite) an dialog.content. Ändere einen Wert und öffne dann das Fenster.
Props ausprobieren
title
description
size
max_width
rx.dialog.root(
rx.dialog.trigger(rx.button("Open dialog")),
rx.dialog.content(
rx.dialog.title("Invite teammates"),
rx.dialog.description("They will get an email with a link."),
rx.flex(
rx.dialog.close(rx.button("Close", variant="soft", color_scheme="gray")),
justify="end",
margin_top="16px",
),
size="3",
max_width="450px",
),
)| Teil | Prop | Werte | Verwendung |
|---|---|---|---|
root | open | True / False | Offen-Zustand über den State steuern (kontrolliert), zusammen mit on_open_change |
root | default_open | True / False | Beim ersten Rendern offen (unkontrolliert) |
root | on_open_change | Event | Beim Öffnen oder Schließen; übergibt den neuen Offen-Wert (bool) |
content | size | "1" ~ "4" | Größe von Innenabstand und Ecken |
content | on_open_auto_focus · on_close_auto_focus | Event | Wenn beim Öffnen das Fenster bzw. beim Schließen der Trigger den Fokus bekommt |
content | on_escape_key_down | Event | Beim Drücken der Esc-Taste |
content | on_pointer_down_outside · on_interact_outside | Event | Bei Klick oder Interaktion außerhalb des Fensters |
trigger, title, description und close haben nur die allgemeinen Events. Schließen lässt sich das Fenster auch mit der Esc-Taste oder per Klick außerhalb.
Ein Fenster zum Bearbeiten des Profils: oben Eingabefelder, darunter nebeneinander die Buttons zum Abbrechen und Speichern. Beide Buttons sind mit dialog.close umschlossen, ein Klick schließt also das Fenster. Wie die Werte tatsächlich gespeichert werden, zeigen der Abschnitt „Formular absenden“ und der Auftrag weiter unten.
rx.dialog.root(
rx.dialog.trigger(rx.button("Edit Profile", size="4")),
rx.dialog.content(
rx.dialog.title("Edit Profile"),
rx.dialog.description(
"Change your profile details and preferences.",
size="2",
margin_bottom="16px",
),
rx.flex(
rx.text("Name", as_="div", size="2", margin_bottom="4px", weight="bold"),
rx.input(default_value="Freja Johnson", placeholder="Enter your name"),
rx.text("Email", as_="div", size="2", margin_bottom="4px", weight="bold"),
rx.input(default_value="freja@example.com", placeholder="Enter your email"),
direction="column",
spacing="3",
),
rx.flex(
rx.dialog.close(
rx.button("Cancel", color_scheme="gray", variant="soft"),
),
rx.dialog.close(
rx.button("Save"),
),
spacing="3",
margin_top="16px",
justify="end",
),
),
)Mit rx.inset(side="x") reichen Inhalte wie Tabellen bis an den linken und rechten Rand des Fensters.
rx.dialog.root(
rx.dialog.trigger(rx.button("View users", size="4")),
rx.dialog.content(
rx.dialog.title("Users"),
rx.dialog.description("The following users have access to this project."),
rx.inset(
rx.table.root(
rx.table.header(
rx.table.row(
rx.table.column_header_cell("Full Name"),
rx.table.column_header_cell("Email"),
rx.table.column_header_cell("Group"),
),
),
rx.table.body(
rx.table.row(
rx.table.row_header_cell("Danilo Rosa"),
rx.table.cell("danilo@example.com"),
rx.table.cell("Developer"),
),
rx.table.row(
rx.table.row_header_cell("Zahra Ambessa"),
rx.table.cell("zahra@example.com"),
rx.table.cell("Admin"),
),
),
),
side="x",
margin_top="24px",
margin_bottom="24px",
),
rx.flex(
rx.dialog.close(
rx.button("Close", variant="soft", color_scheme="gray"),
),
spacing="3",
justify="end",
),
),
)on_open_change an dialog.root übergibt beim Öffnen True und beim Schließen False. Damit zählt man etwa, wie oft das Fenster geöffnet wurde, oder räumt beim Schließen die Eingaben auf.
Opened or closed: 0 times
Dialog open: no
class DialogEventState(rx.State):
num_opens: int = 0
opened: bool = False
@rx.event
def count_opens(self, value: bool):
self.opened = value
self.num_opens += 1
rx.flex(
rx.text("Opened or closed: ", DialogEventState.num_opens, " times"),
rx.text("Dialog open: ", rx.cond(DialogEventState.opened, "yes", "no")),
rx.dialog.root(
rx.dialog.trigger(rx.button("Open Dialog")),
rx.dialog.content(
rx.dialog.title("Welcome to Reflex!"),
rx.dialog.description(
"This is a dialog component. You can render anything you want in here.",
),
rx.dialog.close(
rx.button("Close Dialog", size="3"),
),
),
on_open_change=DialogEventState.count_opens,
),
direction="column",
spacing="3",
align="start",
)Verbindest du open mit einem State-Wert, kann der Code das Fenster auch ohne dialog.trigger öffnen. Unten setzt jeder der beiden Buttons einen anderen Wert und öffnet dann das Fenster. Ist on_open_change mit angebunden, zieht der State auch dann mit, wenn das Fenster per Esc-Taste oder Klick außerhalb geschlossen wird.
Wie man einen Dialog aus einem Eintrag eines Dropdown-Menüs heraus öffnet, zeigt die Seite Dropdown Menu.
class DialogControlState(rx.State):
open: bool = False
seconds: int = 0
@rx.event
def set_open(self, value: bool):
self.open = value
@rx.event
def start(self, seconds: int):
self.seconds = seconds
self.open = True
@rx.event
def confirm(self):
self.open = False
rx.flex(
rx.button("Break: 5 min", variant="soft", on_click=DialogControlState.start(5)),
rx.button("Break: 15 min", variant="soft", on_click=DialogControlState.start(15)),
rx.dialog.root(
rx.dialog.content(
rx.dialog.title("Take a break"),
rx.dialog.description("Stand up and stretch for ", DialogControlState.seconds, " minutes."),
rx.flex(rx.button("OK", on_click=DialogControlState.confirm), justify="end", margin_top="16px"),
max_width="380px",
),
open=DialogControlState.open,
on_open_change=DialogControlState.set_open,
),
spacing="3",
wrap="wrap",
)Steht ein rx.form im Fenster, bekommst du alle Eingaben auf einmal. Umschließt du den Absenden-Button mit dialog.close, schließt sich das Fenster gleichzeitig mit dem Absenden. Der Handler erhält ein dict mit den name-Werten als Schlüsseln und zeigt eine Benachrichtigung (Toast) an.
class DialogFormState(rx.State):
current_user: dict[str, str] = {}
@rx.event
def add_user(self, form_data: dict):
self.current_user = form_data
# Here you would save the user to a database (see the Database course).
return rx.toast.info(
f"User {form_data.get('name', '')} has been added.", position="bottom-right"
)
rx.dialog.root(
rx.dialog.trigger(
rx.button(rx.icon("plus", size=26), rx.text("Add User", size="4")),
),
rx.dialog.content(
rx.dialog.title("Add New User"),
rx.dialog.description("Fill the form with the user's info"),
rx.form(
rx.flex(
rx.input(placeholder="User Name", name="name"),
rx.input(placeholder="user@reflex.dev", name="email"),
rx.flex(
rx.dialog.close(
rx.button("Cancel", variant="soft", color_scheme="gray"),
),
rx.dialog.close(
rx.button("Submit", type="submit"),
),
spacing="3",
justify="end",
),
direction="column",
spacing="4",
),
on_submit=DialogFormState.add_user,
reset_on_submit=False,
),
max_width="450px",
),
)Das Beispiel in der offiziellen Doku speichert an derselben Stelle in eine Datenbank. Nur dieser Teil sieht so aus (auf dieser Seite wird er nicht ausgeführt):
from sqlmodel import select
class User(rx.Model, table=True):
name: str
email: str
@rx.event
def add_user_to_db(self, form_data: dict):
with rx.session() as session:
if session.exec(select(User).where(User.email == form_data["email"])).first():
return rx.window_alert("User with this email already exists")
session.add(User(**form_data))
session.commit()
return rx.toast.info(f"User {form_data['name']} has been added.")Diesmal steuern wir das Fenster über den State. Der Speichern-Button ist nicht mit dialog.close umschlossen; stattdessen speichert der Submit-Handler die Werte und schließt das Fenster dann mit self.open = False. So schließt es sich erst, wenn das Speichern erledigt ist. Die Eingabefelder sind per default_value mit den aktuellen Werten vorbelegt.
Freja Johnson
freja@example.com
class DialogProfileState(rx.State):
open: bool = False
name: str = "Freja Johnson"
email: str = "freja@example.com"
@rx.event
def set_open(self, value: bool):
self.open = value
@rx.event
def save(self, form_data: dict):
self.name = form_data.get("name", "").strip() or self.name
self.email = form_data.get("email", "").strip() or self.email
self.open = False
return rx.toast.success("Profile saved")
rx.card(
rx.flex(
rx.avatar(fallback="FJ", radius="full"),
rx.box(
rx.text(DialogProfileState.name, weight="bold"),
rx.text(DialogProfileState.email, size="2", color_scheme="gray"),
),
rx.spacer(),
rx.dialog.root(
rx.dialog.trigger(rx.button(rx.icon("pencil"), "Edit profile", variant="soft", size="2")),
rx.dialog.content(
rx.dialog.title("Edit profile"),
rx.dialog.description("Change your name and email.", size="2", margin_bottom="12px"),
rx.form(
rx.flex(
rx.input(name="name", default_value=DialogProfileState.name, placeholder="Name"),
rx.input(name="email", default_value=DialogProfileState.email, placeholder="Email", type="email"),
rx.flex(
rx.dialog.close(rx.button("Cancel", variant="soft", color_scheme="gray", type="button")),
rx.button("Save", type="submit"),
spacing="3",
justify="end",
),
direction="column",
spacing="3",
),
on_submit=DialogProfileState.save,
),
max_width="420px",
),
open=DialogProfileState.open,
on_open_change=DialogProfileState.set_open,
),
spacing="3",
align="center",
),
max_width="460px",
)Werkstattnotizen
root · trigger · content · title · description · close. title immer setzen (Screenreader lesen ihn vor).
Größe über size ("1" bis "4") und max_width an content; Inhalte bis an den Rand mit rx.inset.
on_open_change übergibt den neuen Offen-Wert (bool). Mit open gesteuert, öffnet er sich auch ohne trigger.
Formulare mit rx.form + on_submit. Zum Schließen beim Absenden mit close umschließen oder im Handler open auf False setzen.
Für Fenster, die zwingend eine Antwort brauchen (Bestätigen/Abbrechen), nimm den Alert Dialog.
Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
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© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.