コンポーネント工房:Reflexライブラリ100
·
講座の概要
レイアウト
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
タイポグラフィ
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
フォーム
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
データ表示
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
開閉と切り替え
·
Tabs
·
Accordion
·
Segmented Control
オーバーレイ
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
動的レンダリング
·
Cond
·
Match
·
Foreach
·
Auto Scroll
メディア
·
Image
·
Audio
·
Video
表とデータグリッド
·
Table
·
Data Table
·
Data Editor
チャート
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
チャートの部品
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
ほかのチャートライブラリ
·
Plotly
·
Pyplot
HTML要素
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
そのほかの道具
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.selectrx.select.rootrx.select.triggerrx.select.contentrx.select.grouprx.select.labelrx.select.itemrx.select.separator公式ドキュメント
工房の注文書
商品一覧の上にカテゴリーのドロップダウンを付けてください。選んだカテゴリーの商品だけが下に表示されるようにしてください。
rx.selectはクリックすると開くリストから値をひとつ選ぶドロップダウンです。Radix UI の上に作られていてキーボードでも選べ、デスクトップでもモバイルでも同じように動きます。リストをひとつ渡すだけで、ボタンとリストが一緒に作られます。
rx.select.root …)で行います。rx.select(["apple", "grape", "pear"])placeholderは何も選んでいないときだけ表示されます。position="popper"ならリストはボタンの下に開き、"item-aligned"(既定)なら選んだ選択肢がボタンの位置に重なるように開きます。
プロパティを変えてみる
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)| プロパティ | 値 | 既定値 | 用途 |
|---|---|---|---|
最初の引数(items) | 文字列のリスト / Var | 必須 | 選択肢のリスト。値と表示される文字が同じ |
value | 文字列 / Var | なし | 制御する選択値(on_changeと併用) |
default_value | 文字列 | なし | 最初に一度だけ選ぶ値 |
placeholder | 文字列 | "" | 選ぶ前にボタンに表示される案内文 |
label | 文字列 | なし | 開いたリストの一番上に出るグループの見出し |
variant | "classic" "surface" "soft" "ghost" | "surface" | ボタンの見た目 |
size | "1" ~ "3" | "2" | 大きさ |
color_scheme, radius, high_contrast | テーマの値 | 色、ボタンの角の丸み、リストのコントラスト | |
position | "item-aligned" "popper" | "item-aligned" | リストの開き方。ダイアログの中では popper |
width | CSS の長さ | なし | ボタンの幅 |
open / default_open | True / False | False | リストの開閉を制御 / 最初から開いておく |
name, required, disabled | フォーム送信時の名前、選ばないと送信できない、無効化 | ||
on_change | イベント | 別の選択肢を選んだとき。値(文字列)を渡す | |
on_open_change | イベント | リストが開閉したとき。True/Falseを渡す |
いちばんよくある使い方です。valueに State 変数を、on_changeにその変数を更新するハンドラーをつなぎます。選択は常に State の値を表示するので、アプリのどこで値を変えてもドロップダウンが追従します。
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",
)State が不要で最初の選択だけ決めたいならdefault_valueを使います(非制御)。フォーム送信時にだけ値が必要なら、これで十分です。空の状態から始めて選択を促したいなら、default_valueを外してplaceholderを渡します。disabled=Trueなら薄く表示され、開きません。
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",
)選択肢はたいていデータベースや API から来ます。リストの代わりに State のリスト Var を渡せば、リストが変わったときに選択肢も変わります。内部ではrx.foreachで選択肢を作ります。
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が送信データのキーになり、required=Trueなら選ぶまで送信されません。選ばれていない select は空の値("")として入ります。
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",
)高水準のrx.selectは値と表示される文字が同じです。ユーザー名を表示して ID を使いたいなら、公式ドキュメントのように計算変数で名前から ID を引けます。
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"),
)ドロップダウンの中で直接分けたいなら、低水準 API でrx.select.item("表示する文字", value="値")のように書きます。on_changeは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",
)Dialog のように画面の上に浮かぶコンテナの中ではposition="popper"を渡します。そうするとリストがダイアログに切り取られず、ボタンのすぐ下に開きます。
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はリストが開くとTrue、閉じるとFalseを渡します。開いたときにデータを先読みしたり、回数を数えたりするのに使います。
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",
),
)高水準のrx.selectは、下の部品を代わりに組み立ててくれるものです。自分で組み立てれば、グループの見出しや区切り線を入れたり、選択肢をひとつだけ無効にしたりできます。
| 部品 | 役割 | 主なプロパティ |
|---|---|---|
rx.select.root | 全体と選択値 | value default_value on_change open default_open on_open_change name required disabled size |
rx.select.trigger | クリックするボタン | placeholder variant color_scheme radius |
rx.select.content | 開いたリスト | position side side_offset align align_offset variant("solid" "soft") color_scheme high_contrast |
rx.select.group | 選択肢のグループ | |
rx.select.label | グループの見出し | |
rx.select.item | 選択肢ひとつ | value(必須) disabled |
rx.select.separator | 区切り線 |
rx.select.contentにはon_escape_key_down、on_pointer_down_outside、on_close_auto_focusイベントもあります。下は、グループが2つ、区切り線、無効な選択肢(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",
)低水準の root でも、value + on_changeで選択を、open + on_open_changeで開閉を State が持てます。ボタンで選択を変えたりリストを開いたりできます。on_open_changeがopenを更新しないと、ボタンを押してもリストが開きも閉じもしないので注意してください。
フォームでは root のnameがキー、選んだ item のvalueが値になります。
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"),
),
)前の select の値によって後ろの select の選択肢が変わるパターンです(地域 → 国)。地域を変えると、ハンドラーが国もその地域の最初の国に合わせるので、後ろの select が存在しない値を指すことはありません。
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",
)select が下に表示するデータを決める、フィルターのパターンです。計算変数filtered_itemsが選んだカテゴリーの商品だけを返し、rx.foreachがカードとして並べます。labelは開いたリストの一番上にグループの見出しとして表示されます。
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",
)工房ノート
rx.select([選択肢...]) で作り、value + on_change で State と結ぶ。初期値だけなら default_value。
選ぶ前の案内は placeholder、ダイアログの中では position="popper"。
選択肢を State のリストで渡すと、リストがデータに追従する。
表示する文字と値が違う、あるいはグループ・区切り線・無効な選択肢が必要なら root · trigger · content · group · label · item · separator。
on_open_change は開く(True)/ 閉じる(False)。open で直接制御するなら、ハンドラーが open を更新すること。
新しい授業・講座のお知らせを受け取る
この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。
R
ReflexKR
触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。
ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する
アフィリエイトと支援について© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
質問と回答
この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。