Bỏ qua để đến nội dung

⚡ Xử lý sự kiện

Học cách xử lý các sự kiện người dùng như click, nhập liệu, hover… ⏱️ 15 phút

Nắm vững cách xử lý events với on_click, on_change, và các event handlers khác.

Trong Declarative UI, event handlers thay đổi state và UI tự động cập nhật:

import flet as ft
@ft.component
def ClickExample():
count, set_count = ft.use_state(0)
return ft.Column([
ft.Text(f"Clicked: {count} times"),
ft.ElevatedButton("Click me!", on_click=lambda _: set_count(count + 1)),
])
def main(page: ft.Page):
page.add(ClickExample())
ft.run(main)

Lưu ý: Dùng lambda _: (với underscore) khi không cần event object.

Khi cần thông tin từ event:

def handle_click(e):
print(e.control) # Control phát sinh event
print(e.control.data) # Data attribute của control
@ft.component
def ItemList():
selected, set_selected = ft.use_state("")
def handle_click(e):
set_selected(e.control.data)
return ft.Column([
ft.Text(f"Selected: {selected}"),
ft.ElevatedButton("Item 1", data="item-1", on_click=handle_click),
ft.ElevatedButton("Item 2", data="item-2", on_click=handle_click),
ft.ElevatedButton("Item 3", data="item-3", on_click=handle_click),
])

✏️ on_change - Xử lý thay đổi giá trị

Phần tiêu đề “✏️ on_change - Xử lý thay đổi giá trị”

Dùng với TextField, Checkbox, Dropdown… trong Declarative style:

@ft.component
def LiveSearch():
query, set_query = ft.use_state("")
return ft.Column([
ft.TextField(
label="Tìm kiếm",
value=query,
on_change=lambda e: set_query(e.control.value),
),
ft.Text(f"Bạn đang tìm: {query}") if query else ft.Container(),
])

Kết quả:

flowchart LR
I["🔍 Tìm kiếm: python"] --> T["Bạn đang tìm: python"]
style I fill:#e3f2fd
@ft.component
def SubmitExample():
items, set_items = ft.use_state([])
input_val, set_input = ft.use_state("")
def handle_submit(_):
if input_val:
set_items([*items, input_val])
set_input("")
return ft.Column([
ft.TextField(
label="Nhập và nhấn Enter",
value=input_val,
on_change=lambda e: set_input(e.control.value),
on_submit=handle_submit,
),
ft.Column([ft.Text(f"• {item}") for item in items]),
])
@ft.component
def FocusExample():
focused, set_focused = ft.use_state(False)
return ft.Container(
content=ft.TextField(
label="Focus me",
on_focus=lambda _: set_focused(True),
on_blur=lambda _: set_focused(False),
),
border=ft.border.all(2, ft.Colors.GREEN if focused else ft.Colors.GREY),
padding=10,
border_radius=10,
)
@ft.component
def HoverCard():
hovered, set_hovered = ft.use_state(False)
return ft.Container(
content=ft.Text("Hover me!"),
bgcolor=ft.Colors.GREEN_200 if hovered else ft.Colors.BLUE_100,
padding=20,
border_radius=10,
on_hover=lambda e: set_hovered(e.data == "true"),
)
import flet as ft
@ft.component
def LoginForm():
username, set_username = ft.use_state("")
password, set_password = ft.use_state("")
message, set_message = ft.use_state("")
msg_color, set_color = ft.use_state(ft.Colors.BLACK)
def login_clicked(_):
if not username:
set_message("Vui lòng nhập username")
set_color(ft.Colors.RED)
elif not password:
set_message("Vui lòng nhập password")
set_color(ft.Colors.RED)
else:
set_message(f"Xin chào, {username}!")
set_color(ft.Colors.GREEN)
def clear_clicked(_):
set_username("")
set_password("")
set_message("")
return ft.Card(
content=ft.Container(
content=ft.Column([
ft.Text("Đăng nhập", size=24, weight=ft.FontWeight.BOLD),
ft.TextField(
label="Username",
width=300,
value=username,
on_change=lambda e: set_username(e.control.value),
),
ft.TextField(
label="Password",
password=True,
width=300,
value=password,
on_change=lambda e: set_password(e.control.value),
),
ft.Text(message, color=msg_color) if message else ft.Container(),
ft.Row([
ft.FilledButton("Đăng nhập", on_click=login_clicked),
ft.OutlinedButton("Xóa", on_click=clear_clicked),
]),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=15),
padding=30,
),
width=350,
)
def main(page: ft.Page):
page.title = "Login Form"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.add(LoginForm())
ft.run(main)

Kết quả:

flowchart TD
subgraph Card["Login Form"]
T["🔐 Đăng nhập"]
U["Username: admin"]
P["Password: ••••"]
M["✅ Xin chào, admin!"]
B["[Đăng nhập] [Xóa]"]
end
T --> U --> P --> M --> B
style Card fill:#ffffff
style M fill:#c8e6c9
Event Sử dụng với Mô tả
on_click Button, Container, Card… Khi click
on_change TextField, Checkbox, Dropdown… Khi giá trị thay đổi
on_submit TextField Khi nhấn Enter
on_focus TextField Khi focus vào
on_blur TextField Khi mất focus
on_hover Container, Card… Khi hover chuột
Imperative (cũ) Declarative (mới)
Thay đổi control.value Gọi set_state(value)
Phải gọi page.update() UI tự động cập nhật
State lưu trong controls State lưu trong hooks

Đã biết xử lý events! Tiếp tục với Components & Observables để học sâu hơn về Declarative UI.