Skip to content

Commit

Permalink
introduce emitEvent and ui.on
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschindler committed Dec 18, 2023
1 parent 34e9d24 commit f4432a4
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 18 deletions.
3 changes: 1 addition & 2 deletions nicegui/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,7 @@ def handle_event(handler: Optional[Callable[..., Any]], arguments: EventArgument
if isinstance(arguments, UiEventArguments):
if arguments.sender.is_ignoring_events:
return
assert arguments.sender.parent_slot is not None
parent_slot = arguments.sender.parent_slot
parent_slot = arguments.sender.parent_slot or arguments.sender.client.layout.default_slot
else:
parent_slot = nullcontext()

Expand Down
23 changes: 23 additions & 0 deletions nicegui/functions/on.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import Any, Callable, Optional, Sequence, Union

from .. import context


def on(type: str, # pylint: disable=redefined-builtin
handler: Optional[Callable[..., Any]] = None,
args: Union[None, Sequence[str], Sequence[Optional[Sequence[str]]]] = None, *,
throttle: float = 0.0,
leading_events: bool = True,
trailing_events: bool = True,
):
"""Subscribe to a global event.
:param type: name of the event
:param handler: callback that is called upon occurrence of the event
:param args: arguments included in the event message sent to the event handler (default: `None` meaning all)
: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`)
"""
context.get_client().layout.on(type, handler, args,
throttle=throttle, leading_events=leading_events, trailing_events=trailing_events)
3 changes: 3 additions & 0 deletions nicegui/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
return element.$refs.qRef[method_name](...args);
}
}
function emitEvent(event_name, ...args) {
getElement(0).$emit(event_name, ...args);
}
</script>
<script type="module">
const True = true;
Expand Down
2 changes: 2 additions & 0 deletions nicegui/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
'footer',
'header',
'left_drawer',
'on',
'page_sticky',
'right_drawer',
'run',
Expand Down Expand Up @@ -190,6 +191,7 @@
from .functions.html import add_body_html, add_head_html
from .functions.javascript import run_javascript
from .functions.notify import notify
from .functions.on import on
from .functions.open import open # pylint: disable=redefined-builtin
from .functions.page_title import page_title
from .functions.refreshable import refreshable, state
Expand Down
34 changes: 18 additions & 16 deletions website/documentation/content/generic_events_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,26 +99,28 @@ def modifiers() -> None:


@doc.demo('Custom events', '''
It is fairly easy to emit custom events from JavaScript which can be listened to with `element.on(...)`.
It is fairly easy to emit custom events from JavaScript with `emitEvent(...)` which can be listened to with `ui.on(...)`.
This can be useful if you want to call Python code when something happens in JavaScript.
In this example we are listening to the `visibilitychange` event of the browser tab.
''')
async def custom_events() -> None:
tabwatch = ui.checkbox('Watch browser tab re-entering') \
.on('tabvisible', lambda: ui.notify('Welcome back!') if tabwatch.value else None, args=[])
ui.add_head_html(f'''
<script>
document.addEventListener('visibilitychange', () => {{
if (document.visibilityState === 'visible')
getElement({tabwatch.id}).$emit('tabvisible');
}});
</script>
''')
tabwatch = ui.checkbox('Watch browser tab re-entering')
ui.on('tabvisible', lambda: ui.notify('Welcome back!') if tabwatch.value else None)
# ui.add_head_html('''
# <script>
# document.addEventListener('visibilitychange', () => {
# if (document.visibilityState === 'visible') {
# emitEvent('tabvisible');
# }
# });
# </script>
# ''')
# END OF DEMO
await context.get_client().connected()
ui.run_javascript(f'''
document.addEventListener('visibilitychange', () => {{
if (document.visibilityState === 'visible')
getElement({tabwatch.id}).$emit('tabvisible');
}});
ui.run_javascript('''
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
emitEvent('tabvisible');
}
});
''')

0 comments on commit f4432a4

Please sign in to comment.