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.selectrx.select.rootrx.select.triggerrx.select.contentrx.select.grouprx.select.labelrx.select.itemrx.select.separatorOffizielle Doku
Werkstattauftrag
Bitte setz über die Produktliste ein Kategorie-Dropdown. Darunter sollen nur die Produkte der gewählten Kategorie erscheinen.
rx.select ist ein Dropdown, bei dem man aus einer aufklappenden Liste einen Wert wählt. Es baut auf Radix UI auf, lässt sich auch per Tastatur bedienen und verhält sich auf Desktop und Mobilgeräten gleich. Übergibst du nur eine Liste, entstehen Button und Liste zusammen.
rx.select.root …).rx.select(["apple", "grape", "pear"])placeholder erscheint nur, solange nichts gewählt ist. Mit position="popper" klappt die Liste unter dem Button auf, mit "item-aligned" (Standard) so, dass die gewählte Option über dem Button liegt.
Props ausprobieren
placeholder
variant
size
color
radius
position
high_contrast
disabled
rx.select(["apple", "grape", "pear"], placeholder="Choose a fruit...", variant="surface", size="2", color_scheme="indigo", radius="medium", position="item-aligned", high_contrast=False, disabled=False)| Prop | Werte | Standard | Verwendung |
|---|---|---|---|
Erstes Argument (items) | Liste von Strings / Var | erforderlich | Optionen. Wert und angezeigter Text sind gleich |
value | String / Var | keiner | Gesteuerte Auswahl (zusammen mit on_change) |
default_value | String | keiner | Auswahl, die nur einmal am Anfang gesetzt wird |
placeholder | String | "" | Hinweistext auf dem Button vor der Auswahl |
label | String | keiner | Gruppentitel ganz oben in der aufgeklappten Liste |
variant | "classic" "surface" "soft" "ghost" | "surface" | Aussehen des Buttons |
size | "1" bis "3" | "2" | Größe |
color_scheme, radius, high_contrast | Theme-Wert | Farbe, Ecken des Buttons, Kontrast der Liste | |
position | "item-aligned" "popper" | "item-aligned" | Wie die Liste aufklappt. In Dialogen popper |
width | CSS-Länge | keiner | Breite des Buttons |
open / default_open | True / False | False | Offenen Zustand steuern / von Anfang an offen |
name, required, disabled | Name beim Absenden, Auswahl zum Absenden nötig, Sperren | ||
on_change | Event | Wenn eine andere Option gewählt wird. Übergibt den Wert (String) | |
on_open_change | Event | Wenn die Liste auf- oder zuklappt. Übergibt True/False |
Der häufigste Fall: Du verbindest value mit einer State-Variable und on_change mit einem Handler, der diese Variable ändert. Die Auswahl zeigt immer den State-Wert, das Dropdown zieht also mit, egal wo in der App der Wert geändert wird.
You selected:
appleclass SelectFruitState(rx.State):
selected_fruit: str = "apple"
@rx.event
def update_fruit(self, value: str):
self.selected_fruit = value
rx.hstack(
rx.select(
["apple", "grape", "pear"],
value=SelectFruitState.selected_fruit,
on_change=SelectFruitState.update_fruit,
),
rx.text("You selected:"),
rx.badge(SelectFruitState.selected_fruit),
align="center",
spacing="3",
)Brauchst du keinen State und willst nur die Anfangsauswahl festlegen, nimm default_value (ungesteuert). Brauchst du den Wert nur beim Absenden eines Formulars, reicht das völlig. Soll es leer starten und zur Auswahl auffordern, lass default_value weg und setz placeholder. Mit disabled=True ist es abgeblendet und klappt nicht auf.
rx.flex(
rx.select(["apple", "grape", "pear"], default_value="grape"),
rx.select(["apple", "grape", "pear"], placeholder="Choose a fruit..."),
rx.select(["apple", "grape", "pear"], default_value="apple", disabled=True),
spacing="3",
wrap="wrap",
)Optionen kommen meist aus einer Datenbank oder API. Übergibst du statt einer Liste eine Listen-Var aus dem State, ändert sich die Liste mit, wenn sich die Daten ändern. Intern werden die Optionen mit rx.foreach erzeugt.
3 options
import random
class SelectDynamicState(rx.State):
options: list[str] = ["apple", "grape", "pear"]
selected: str = "apple"
@rx.event
def set_selected(self, value: str):
self.selected = value
@rx.event
def randomize(self):
self.selected = random.choice(self.options)
@rx.event
def add_option(self):
new_options = ["banana", "orange", "mango", "kiwi", "cherry"]
available = [o for o in new_options if o not in self.options]
if available:
self.options = self.options + [available[0]]
@rx.event
def reset_options(self):
self.options = ["apple", "grape", "pear"]
self.selected = "apple"
rx.vstack(
rx.select(
SelectDynamicState.options,
value=SelectDynamicState.selected,
on_change=SelectDynamicState.set_selected,
),
rx.hstack(
rx.button("Pick Random", on_click=SelectDynamicState.randomize, size="1"),
rx.button("Add Option", on_click=SelectDynamicState.add_option, size="1", variant="soft"),
rx.button("Reset", on_click=SelectDynamicState.reset_options, size="1", variant="soft", color_scheme="gray"),
),
rx.text(SelectDynamicState.options.length(), " options", size="1", color_scheme="gray"),
)name wird zum Schlüssel der gesendeten Daten, und mit required=True wird erst nach einer Auswahl abgeschickt. Ein Select ohne Auswahl kommt als leerer Wert ("") an.
Results:
{}class SelectFormState(rx.State):
form_data: dict = {}
@rx.event
def handle_submit(self, form_data: dict):
self.form_data = form_data
rx.card(
rx.vstack(
rx.form.root(
rx.vstack(
rx.text("Favorite fruit", size="2"),
rx.select(["apple", "grape", "pear"], name="fruit", placeholder="Pick one", required=True),
rx.text("Quantity", size="2"),
rx.select(["1", "2", "3", "4", "5"], name="quantity", default_value="1"),
rx.button("Submit Order", type="submit"),
spacing="2",
align="stretch",
),
on_submit=SelectFormState.handle_submit,
reset_on_submit=True,
),
rx.divider(),
rx.hstack(rx.text("Results:", weight="bold"), rx.badge(SelectFormState.form_data.to_string())),
spacing="3",
),
width="320px",
)Beim High-Level-rx.select sind Wert und angezeigter Text gleich. Willst du Benutzernamen zeigen, aber mit IDs arbeiten, kannst du wie in der offiziellen Doku per berechneter Variable die ID zum Namen suchen.
Selected user ID: user_001
class SelectUserState(rx.State):
users: dict[str, str] = {
"user_001": "Alice Johnson",
"user_002": "Bob Smith",
"user_003": "Carol Davis",
}
selected_name: str = "Alice Johnson"
@rx.var
def user_names(self) -> list[str]:
return list(self.users.values())
@rx.var
def selected_id(self) -> str:
for uid, name in self.users.items():
if name == self.selected_name:
return uid
return ""
@rx.event
def set_user(self, name: str):
self.selected_name = name
rx.vstack(
rx.select(
SelectUserState.user_names,
value=SelectUserState.selected_name,
on_change=SelectUserState.set_user,
),
rx.text("Selected user ID: ", rx.code(SelectUserState.selected_id), size="2"),
)Um direkt im Dropdown zu trennen, schreibst du mit der Low-Level-API rx.select.item("Angezeigter Text", value="Wert"). on_change übergibt dann value.
value = kr
class SelectCountryState(rx.State):
code: str = "kr"
@rx.event
def set_code(self, value: str):
self.code = value
rx.hstack(
rx.select.root(
rx.select.trigger(),
rx.select.content(
rx.select.item("Korea", value="kr"),
rx.select.item("Japan", value="jp"),
rx.select.item("Germany", value="de"),
),
value=SelectCountryState.code,
on_change=SelectCountryState.set_code,
),
rx.text("value = ", rx.code(SelectCountryState.code), size="2"),
align="center",
)In schwebenden Containern wie Dialog gibst du position="popper" an. Nur dann klappt die Liste direkt unter dem Button auf, ohne vom Dialog abgeschnitten zu werden.
rx.dialog.root(
rx.dialog.trigger(rx.button("Open Dialog")),
rx.dialog.content(
rx.dialog.title("Pick a fruit"),
rx.vstack(
rx.select(["apple", "grape", "pear"], position="popper", default_value="apple"),
rx.dialog.close(rx.button("Close", variant="soft")),
spacing="3",
),
max_width="320px",
),
)on_open_change übergibt beim Aufklappen True und beim Zuklappen False. Damit lädst du beim Öffnen Daten vor oder zählst mit.
Open count: 0
Closedclass SelectOpenState(rx.State):
is_open: bool = False
open_count: int = 0
@rx.event
def on_toggle(self, is_open: bool):
self.is_open = is_open
if is_open:
self.open_count += 1
rx.vstack(
rx.select(["apple", "grape", "pear"], default_value="apple", on_open_change=SelectOpenState.on_toggle),
rx.hstack(
rx.text("Open count: ", SelectOpenState.open_count, size="2"),
rx.cond(
SelectOpenState.is_open,
rx.badge("Open", color_scheme="green"),
rx.badge("Closed", color_scheme="gray"),
),
align="center",
),
)Das High-Level-rx.select setzt nur die folgenden Bausteine für dich zusammen. Baust du sie selbst zusammen, kannst du Gruppentitel und Trennlinien einfügen und einzelne Optionen sperren.
| Baustein | Aufgabe | Wichtige Props |
|---|---|---|
rx.select.root | Ganzes und Auswahl | value default_value on_change open default_open on_open_change name required disabled size |
rx.select.trigger | Der Button zum Klicken | placeholder variant color_scheme radius |
rx.select.content | Die aufgeklappte Liste | position side side_offset align align_offset variant("solid" "soft") color_scheme high_contrast |
rx.select.group | Gruppe von Optionen | |
rx.select.label | Gruppentitel | |
rx.select.item | Eine Option | value (erforderlich) disabled |
rx.select.separator | Trennlinie |
rx.select.content hat außerdem die Events on_escape_key_down, on_pointer_down_outside und on_close_auto_focus. Unten eine Liste mit zwei Gruppen, einer Trennlinie und einer gesperrten Option (Grape).
rx.select.root(
rx.select.trigger(placeholder="Pick a food", variant="soft", radius="full"),
rx.select.content(
rx.select.group(
rx.select.label("Fruits"),
rx.select.item("Orange", value="orange"),
rx.select.item("Apple", value="apple"),
rx.select.item("Grape", value="grape", disabled=True),
),
rx.select.separator(),
rx.select.group(
rx.select.label("Vegetables"),
rx.select.item("Carrot", value="carrot"),
rx.select.item("Potato", value="potato"),
),
position="popper",
side="bottom",
side_offset=6,
variant="soft",
color_scheme="green",
),
size="2",
)Auch beim Low-Level-root kann der State per value + on_change die Auswahl und per open + on_open_change den offenen Zustand halten. So lässt sich die Auswahl per Button ändern oder die Liste öffnen. Achtung: Ändert on_open_change nicht open, klappt die Liste beim Klicken weder auf noch zu.
Im Formular ist name des root der Schlüssel und value des gewählten item der Wert.
class SelectControlState(rx.State):
value: str = "apple"
open: bool = False
@rx.event
def set_value(self, value: str):
self.value = value
@rx.event
def set_open(self, value: bool):
self.open = value
@rx.event
def next_fruit(self):
fruits = ["apple", "grape", "pear"]
self.value = fruits[(fruits.index(self.value) + 1) % 3]
rx.vstack(
rx.select.root(
rx.select.trigger(),
rx.select.content(
rx.select.item("apple", value="apple"),
rx.select.item("grape", value="grape"),
rx.select.item("pear", value="pear"),
),
value=SelectControlState.value,
on_change=SelectControlState.set_value,
open=SelectControlState.open,
on_open_change=SelectControlState.set_open,
),
rx.hstack(
rx.button("Next value", on_click=SelectControlState.next_fruit, size="1", variant="soft"),
rx.button("Open menu", on_click=SelectControlState.set_open(True), size="1", variant="soft"),
),
)Ein Muster, bei dem die Optionen des zweiten Selects vom Wert des ersten abhängen (Region → Land). Ändert sich die Region, setzt der Handler das Land auf das erste Land dieser Region, damit das zweite Select nie auf einen nicht vorhandenen Wert zeigt.
class SelectCascadeState(rx.State):
regions: dict[str, list[str]] = {
"North America": ["USA", "Canada", "Mexico"],
"Europe": ["UK", "France", "Germany"],
"Asia": ["Japan", "Korea", "Singapore"],
}
region: str = "North America"
country: str = "USA"
@rx.event
def set_region(self, value: str):
self.region = value
self.country = self.regions[value][0]
@rx.event
def set_country(self, value: str):
self.country = value
@rx.var
def region_names(self) -> list[str]:
return list(self.regions.keys())
@rx.var
def countries(self) -> list[str]:
return self.regions.get(self.region, [])
rx.hstack(
rx.select(SelectCascadeState.region_names, value=SelectCascadeState.region, on_change=SelectCascadeState.set_region),
rx.select(SelectCascadeState.countries, value=SelectCascadeState.country, on_change=SelectCascadeState.set_country),
spacing="3",
wrap="wrap",
)Ein Filtermuster: Das Select bestimmt, welche Daten darunter erscheinen. Die berechnete Variable filtered_items liefert nur die Produkte der gewählten Kategorie, und rx.foreach reiht sie als Karten auf. label erscheint als Gruppentitel ganz oben in der aufgeklappten Liste.
class SelectFilterState(rx.State):
all_items: list[dict[str, str]] = [
{"name": "MacBook Pro", "category": "laptops"},
{"name": "Dell XPS", "category": "laptops"},
{"name": "iPhone 15", "category": "phones"},
{"name": "Pixel 8", "category": "phones"},
{"name": "iPad Air", "category": "tablets"},
{"name": "Galaxy Tab", "category": "tablets"},
]
category: str = "laptops"
@rx.event
def set_category(self, value: str):
self.category = value
@rx.var
def filtered_items(self) -> list[dict[str, str]]:
return [i for i in self.all_items if i["category"] == self.category]
rx.vstack(
rx.select(
["laptops", "phones", "tablets"],
value=SelectFilterState.category,
on_change=SelectFilterState.set_category,
label="Category",
),
rx.foreach(SelectFilterState.filtered_items, lambda item: rx.card(item["name"], width="100%")),
spacing="3",
width="280px",
)Werkstattnotizen
Mit rx.select([Optionen...]) anlegen und per value + on_change an den State binden. Nur Anfangswert: default_value.
Hinweis vor der Auswahl per placeholder, in Dialogen position="popper".
Übergibst du die Optionen als State-Liste, folgt die Liste den Daten.
Weichen Text und Wert ab oder brauchst du Gruppen · Trennlinien · gesperrte Optionen: root · trigger · content · group · label · item · separator.
on_open_change meldet offen (True)/geschlossen (False). Steuerst du open selbst, muss der Handler open ändern.
Ü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.