|
@@ -13,7 +13,7 @@ from . import context, core, events, helpers, json, storage
|
|
|
from .awaitable_response import AwaitableResponse, NullResponse
|
|
|
from .dependencies import Component, Library, register_library, register_resource, register_vue_component
|
|
|
from .elements.mixins.visibility import Visibility
|
|
|
-from .event_listener import EventListener
|
|
|
+from .event_listener import EventListener, JSEventListener
|
|
|
from .slot import Slot
|
|
|
from .tailwind import Tailwind
|
|
|
from .version import __version__
|
|
@@ -85,6 +85,7 @@ class Element(Visibility):
|
|
|
self._props: Dict[str, Any] = {'key': self.id} # HACK: workaround for #600 and #898
|
|
|
self._props.update(self._default_props)
|
|
|
self._event_listeners: Dict[str, EventListener] = {}
|
|
|
+ self._js_event_listeners: List[JSEventListener] = []
|
|
|
self._text: Optional[str] = None
|
|
|
self.slots: Dict[str, Slot] = {}
|
|
|
self.default_slot = self.add_slot('default')
|
|
@@ -187,6 +188,8 @@ class Element(Visibility):
|
|
|
}
|
|
|
|
|
|
def _to_dict(self) -> Dict[str, Any]:
|
|
|
+ events = [listener.to_dict() for listener in self._event_listeners.values()]
|
|
|
+ events.extend([listener.to_dict() for listener in self._js_event_listeners])
|
|
|
return {
|
|
|
'id': self.id,
|
|
|
'tag': self.tag,
|
|
@@ -195,7 +198,7 @@ class Element(Visibility):
|
|
|
'props': self._props,
|
|
|
'text': self._text,
|
|
|
'slots': self._collect_slot_dict(),
|
|
|
- 'events': [listener.to_dict() for listener in self._event_listeners.values()],
|
|
|
+ 'events': events,
|
|
|
'component': {
|
|
|
'key': self.component.key,
|
|
|
'name': self.component.name,
|
|
@@ -395,6 +398,7 @@ class Element(Visibility):
|
|
|
throttle: float = 0.0,
|
|
|
leading_events: bool = True,
|
|
|
trailing_events: bool = True,
|
|
|
+ js_handler: Optional[str] = None,
|
|
|
) -> Self:
|
|
|
"""Subscribe to an event.
|
|
|
|
|
@@ -404,7 +408,11 @@ class Element(Visibility):
|
|
|
:param throttle: minimum time (in seconds) between event occurrences (default: 0.0)
|
|
|
:param leading_events: whether to trigger the event handler immediately upon the first event occurrence (default: `True`)
|
|
|
:param trailing_events: whether to trigger the event handler after the last event occurrence (default: `True`)
|
|
|
+ :param js_handler: JavaScript code that is executed upon occurrence of the event, e.g. `(evt) => alert(evt)` (default: `None`)
|
|
|
"""
|
|
|
+ if not ((js_handler is None) ^ (handler is None)):
|
|
|
+ raise ValueError('Either handler or js_handler must be specified, but not both')
|
|
|
+
|
|
|
if handler:
|
|
|
listener = EventListener(
|
|
|
element_id=self.id,
|
|
@@ -418,6 +426,13 @@ class Element(Visibility):
|
|
|
)
|
|
|
self._event_listeners[listener.id] = listener
|
|
|
self.update()
|
|
|
+ if js_handler:
|
|
|
+ listener = JSEventListener(
|
|
|
+ type=helpers.kebab_to_camel_case(type),
|
|
|
+ js_handler=js_handler,
|
|
|
+ )
|
|
|
+ self._js_event_listeners.append(listener)
|
|
|
+ self.update()
|
|
|
return self
|
|
|
|
|
|
def _handle_event(self, msg: Dict) -> None:
|