Skip to content

add event handlers docs #410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install Python Dependencies
run: pip install -r requirements/test-run.txt
- name: Run Tests
run: nox -s test --verbose -- --headless
run: nox -s test -- --headless
test-python-versions:
runs-on: ${{ matrix.os }}
strategy:
Expand All @@ -54,7 +54,7 @@ jobs:
- name: Install Python Dependencies
run: pip install -r requirements/test-run.txt
- name: Run Tests
run: nox -s test --verbose -- --headless --no-cov
run: nox -s test -- --headless --no-cov
test-javascript:
runs-on: ubuntu-latest
steps:
Expand Down
21 changes: 21 additions & 0 deletions docs/source/examples/play_audio_sound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import json

import idom


@idom.component
def PlayDinosaurSound():
event, set_event = idom.hooks.use_state(None)
return idom.html.div(
idom.html.audio(
{
"controls": True,
"onTimeUpdate": lambda e: set_event(e),
"src": "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
}
),
idom.html.pre(json.dumps(event, indent=2)),
)


idom.run(PlayDinosaurSound)
18 changes: 18 additions & 0 deletions docs/source/examples/prevent_default_event_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import idom


@idom.component
def DoNotChangePages():
return idom.html.div(
idom.html.p("Normally clicking this link would take you to a new page"),
idom.html.a(
{
"onClick": idom.event(lambda e: None, prevent_default=True),
"href": "https://google.com",
},
"https://google.com",
),
)


idom.run(DoNotChangePages)
15 changes: 15 additions & 0 deletions docs/source/examples/show_click_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import json

import idom


@idom.component
def BasicButton():
event, set_event = idom.hooks.use_state(None)
return idom.html.div(
idom.html.button({"onClick": lambda e: set_event(e)}, "click to see event"),
idom.html.pre(json.dumps(event, indent=2)),
)


idom.run(BasicButton)
38 changes: 38 additions & 0 deletions docs/source/examples/stop_event_propagation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import idom


@idom.component
def DivInDiv():
stop_propagatation, set_stop_propagatation = idom.hooks.use_state(True)
inner_count, set_inner_count = idom.hooks.use_state(0)
outer_count, set_outer_count = idom.hooks.use_state(0)

div_in_div = idom.html.div(
{
"onClick": idom.event(lambda e: set_outer_count(outer_count + 1)),
"style": {"height": "100px", "width": "100px", "backgroundColor": "red"},
},
idom.html.div(
{
"onClick": idom.event(
lambda e: set_inner_count(inner_count + 1),
stop_propagation=stop_propagatation,
),
"style": {"height": "50px", "width": "50px", "backgroundColor": "blue"},
},
),
)

return idom.html.div(
idom.html.button(
{"onClick": lambda e: set_stop_propagatation(not stop_propagatation)},
"Toggle Propogation",
),
idom.html.pre(f"Will stop propagation: {stop_propagatation}"),
idom.html.pre(f"Inner click count: {inner_count}"),
idom.html.pre(f"Outer click count: {outer_count}"),
div_in_div,
)


idom.run(DivInDiv)
2 changes: 1 addition & 1 deletion docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ favorite Python packages with IDOM.
Does IDOM transpile Python to Javascript?
-----------------------------------------

No. As in the answer to :ref:`Do UI components run server-side?`, IDOM runs almost
No. As in the answer to :ref:`Do UI components run client-side?`, IDOM runs almost
everything server-side and in Python. This was an explicit design choice to keep things
simple and one which allows you to do everything you normally would in Python.

Expand Down
62 changes: 62 additions & 0 deletions docs/source/handling-events.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Handling Events
===============

When :ref:`Getting Started`, we saw how IDOM makes it possible to write server-side code
that defines basic views and can react to client-side events. The simplest way to listen
and respond to events is by assigning a callable object to a :ref:`VDOM <VDOM Mimetype>`
an attribute where event signals are sent. This is relatively similar to
`handling events in React`_:

.. _handling events in React: https://reactjs.org/docs/handling-events.html

.. example:: show_click_event


Differences With React Events
-----------------------------

Because IDOM operates server-side, there are inevitable limitations that prevent it from
achieving perfect parity with all the behaviors of React. With that said, any feature
that cannot be achieved in Python with IDOM, can be done by creating
:ref:`Custom Javascript Components`.


Preventing Default Event Actions
................................

Instead of calling an ``event.preventDefault()`` method as you would do in React, you
must declare whether to prevent default behavior ahead of time. This can be accomplished
using the :func:`~idom.core.events.event` decorator and setting ``prevent_default``. For
example, we can stop a link from going to the specified URL:

.. example:: prevent_default_event_actions

Unfortunately this means you cannot conditionally prevent default behavior in response
to event data without writing :ref:`Custom Javascript Components`.


Stop Event Propogation
......................

Similarly to :ref:`preventing default behavior <Preventing Default Event Actions>`, you
can use the :func:`~idom.core.events.event` decorator to forward declare whether or not
you want events from a child element propogate up through the document to parent
elements by setting ``stop_propagation``. In the example below we place a red ``div``
inside a parent blue ``div``. When propogation is turned on, clicking the red element
will cause the handler for the outer blue one to fire. Conversely, when it's off, only
the handler for the red element will fire.

.. example:: stop_event_propagation


Event Data Serialization
........................

Not all event data is serialized. The most notable example of this is the lack of a
``target`` key in the dictionary sent back to the handler. Instead, data which is not
inherhently JSON serializable must be treated on a case-by-case basis. A simple case
to demonstrate this is the ``currentTime`` attribute of ``audio`` and ``video``
elements. Normally this would be accessible via ``event.target.currenTime``, but here
it's simply passed in under the key ``currentTime``:

.. example:: play_audio_sound
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ IDOM

.. toctree::
:hidden:
:caption: User Guide

installation
getting-started
handling-events
life-cycle-hooks
auto/api-reference
examples
Expand Down