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
Overlays

Dialog

rx.dialog.rootrx.dialog.triggerrx.dialog.contentrx.dialog.titlerx.dialog.descriptionrx.dialog.close

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

Props ausprobieren

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",
    ),
)
size ändert Innenabstand und Ecken zugleich. Die Breite legst du mit Style-Props wie max_width fest.
TeilPropWerteVerwendung
rootopenTrue / FalseOffen-Zustand über den State steuern (kontrolliert), zusammen mit on_open_change
rootdefault_openTrue / FalseBeim ersten Rendern offen (unkontrolliert)
rooton_open_changeEventBeim Öffnen oder Schließen; übergibt den neuen Offen-Wert (bool)
contentsize"1" ~ "4"Größe von Innenabstand und Ecken
contenton_open_auto_focus · on_close_auto_focusEventWenn beim Öffnen das Fenster bzw. beim Schließen der Trigger den Fokus bekommt
contenton_escape_key_downEventBeim Drücken der Esc-Taste
contenton_pointer_down_outside · on_interact_outsideEventBei 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.

Aus der Praxis: ein Fenster mit Eingabefeldern

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

Beim Öffnen und Schließen: on_open_change

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

Öffnen und Schließen über den State

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

Formular absenden

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

Auftrag erledigt

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.

← Zurück

Overlays · Hover Card

Weiter →

Overlays · Alert Dialog

Ü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