0
# Event Handling
1
2
Event system for handling user interactions with proper event delegation and prevention. ReactPy provides a decorator-based approach to event handling that works seamlessly with HTML elements.
3
4
## Capabilities
5
6
### Event Decorator
7
8
The `@event` decorator creates event handlers with optional event behavior control:
9
10
```python { .api }
11
@event(prevent_default: bool = False, stop_propagation: bool = False)
12
def event_handler(event_data: dict) -> None: ...
13
```
14
15
**Parameters:**
16
- `prevent_default`: Whether to prevent the default browser action
17
- `stop_propagation`: Whether to stop event bubbling
18
19
**Returns:** EventHandler instance
20
21
### EventHandler Class
22
23
The EventHandler class wraps event functions with metadata:
24
25
```python { .api }
26
class EventHandler:
27
function: Callable[[dict], None]
28
prevent_default: bool
29
stop_propagation: bool
30
```
31
32
### Basic Event Handling
33
34
```python
35
from reactpy import component, html, event
36
37
@component
38
def ClickableButton():
39
@event
40
def handle_click(event_data):
41
print(f"Button clicked! Event: {event_data}")
42
43
return html.button(
44
{"onClick": handle_click},
45
"Click Me"
46
)
47
```
48
49
### Event Prevention
50
51
```python
52
@component
53
def FormWithValidation():
54
@event(prevent_default=True) # Prevent form submission
55
def handle_submit(event_data):
56
# Custom validation logic
57
if not validate_form():
58
print("Form invalid!")
59
return
60
# Process form submission
61
submit_form()
62
63
return html.form(
64
{"onSubmit": handle_submit},
65
html.input({"type": "text", "required": True}),
66
html.button({"type": "submit"}, "Submit")
67
)
68
```
69
70
### Event Propagation Control
71
72
```python
73
@component
74
def NestedClickHandlers():
75
@event
76
def outer_click(event_data):
77
print("Outer clicked")
78
79
@event(stop_propagation=True) # Stop bubbling
80
def inner_click(event_data):
81
print("Inner clicked - won't bubble")
82
83
return html.div(
84
{"onClick": outer_click, "style": {"padding": "20px", "border": "1px solid"}},
85
"Outer div",
86
html.button(
87
{"onClick": inner_click},
88
"Inner button"
89
)
90
)
91
```
92
93
### Common Event Types
94
95
ReactPy supports all standard DOM events:
96
97
```python
98
@component
99
def EventExamples():
100
@event
101
def handle_input(event_data):
102
value = event_data.get("target", {}).get("value", "")
103
print(f"Input value: {value}")
104
105
@event
106
def handle_focus(event_data):
107
print("Input focused")
108
109
@event
110
def handle_blur(event_data):
111
print("Input blurred")
112
113
@event
114
def handle_keydown(event_data):
115
key = event_data.get("key", "")
116
if key == "Enter":
117
print("Enter key pressed")
118
119
return html.div(
120
html.input({
121
"onInput": handle_input,
122
"onFocus": handle_focus,
123
"onBlur": handle_blur,
124
"onKeyDown": handle_keydown,
125
"placeholder": "Type here..."
126
})
127
)
128
```
129
130
### Event Data Structure
131
132
Event data contains standard DOM event properties:
133
134
```python
135
@component
136
def EventDataExample():
137
@event
138
def handle_mouse_event(event_data):
139
# Common properties available in event_data:
140
event_type = event_data.get("type") # "click", "mousedown", etc.
141
142
# Mouse events
143
x = event_data.get("clientX")
144
y = event_data.get("clientY")
145
button = event_data.get("button") # 0=left, 1=middle, 2=right
146
147
# Keyboard events
148
key = event_data.get("key")
149
alt_key = event_data.get("altKey")
150
ctrl_key = event_data.get("ctrlKey")
151
shift_key = event_data.get("shiftKey")
152
153
# Target element
154
target = event_data.get("target", {})
155
value = target.get("value") # For input elements
156
tag_name = target.get("tagName")
157
158
print(f"Event: {event_type} at ({x}, {y})")
159
160
return html.div(
161
{"onMouseDown": handle_mouse_event},
162
"Click me to see event data"
163
)
164
```
165
166
### State Updates in Event Handlers
167
168
Event handlers commonly update component state:
169
170
```python
171
@component
172
def Counter():
173
count, set_count = use_state(0)
174
175
@event
176
def increment(event_data):
177
set_count(count + 1)
178
179
@event
180
def decrement(event_data):
181
set_count(count - 1)
182
183
@event
184
def reset(event_data):
185
set_count(0)
186
187
return html.div(
188
html.h2(f"Count: {count}"),
189
html.button({"onClick": increment}, "+"),
190
html.button({"onClick": decrement}, "-"),
191
html.button({"onClick": reset}, "Reset")
192
)
193
```
194
195
### Form Event Handling
196
197
Special patterns for form events:
198
199
```python
200
@component
201
def ContactForm():
202
form_data, set_form_data = use_state({"name": "", "email": ""})
203
204
@event
205
def handle_input_change(event_data):
206
field_name = event_data["target"]["name"]
207
field_value = event_data["target"]["value"]
208
set_form_data({
209
**form_data,
210
field_name: field_value
211
})
212
213
@event(prevent_default=True)
214
def handle_submit(event_data):
215
print(f"Submitting: {form_data}")
216
# Process form submission
217
218
return html.form(
219
{"onSubmit": handle_submit},
220
html.input({
221
"name": "name",
222
"value": form_data["name"],
223
"onInput": handle_input_change,
224
"placeholder": "Name"
225
}),
226
html.input({
227
"name": "email",
228
"type": "email",
229
"value": form_data["email"],
230
"onInput": handle_input_change,
231
"placeholder": "Email"
232
}),
233
html.button({"type": "submit"}, "Submit")
234
)
235
```