Repository navigation
Events and Async
Register handlers with a widget's .on_* methods. Payloads arrive converted to
Python dicts, and most handlers receive one dict:
tree.on_select(lambda p: show(p["id"], p["node"]))
table.on_action(lambda p: run(p["action"], p["selected"]))
form.on_submit(lambda values: save(values))Each widget's page lists its payloads. Handlers run synchronously, inside the browser event that triggered them.
BFF classes get an awaitable name_async() companion for every export. Call
that one: the plain name() is a blocking request, deprecated through
pyTincture 1.x. Handlers and load_ui() are synchronous, so schedule the
coroutine, and report its exceptions, because asyncio.ensure_future
swallows them:
import asyncio, traceback
import js
def spawn(coro, label):
async def guarded():
try:
await coro
except Exception:
js.console.error(f"{label} failed:\n{traceback.format_exc()}")
return asyncio.ensure_future(guarded())
form.on_submit(lambda values: spawn(self.save(values), "save"))
async def save(self, values):
self.form.set_busy(True)
try:
result = await Store().save_async(values)
finally:
self.form.set_busy(False)Never call asyncio.run in the browser. It creates and closes a second
event loop and breaks Pyodide's loop for the rest of the session.
pyTincture re-executes a BFF module's source for every call, so module-level lists, caches and locks are recreated per request. Keep state in storage, or in an ordinary module the BFF imports by name.
-
wapyt payloads and getters give real
Nonefor JSnull(since #29). -
Your own JS calls don't. In code that calls the DOM or JS directly, JS
nullarrives asJsNull, which is notNone:js.document.getElementById("x")returnsJsNullwhen the element is missing, andif el is None:never fires. Test truthiness (if not el:), or pass the value throughwapyt._runtime.to_plain(). - A missing JS property raises
AttributeErrorinstead of returningundefined. UsegetAttribute()orhasattr()rather thanelement.dataset.foo. - Pass
js.undefinedwhere a JS API distinguishes "absent" fromnull. - DOM listeners you add yourself need
pyodide.ffi.create_proxy(fn); keep a reference to the proxy for as long as the listener lives.
wapyt is MIT-licensed · Repository · pyTincture · Issues
Getting started
Widgets
- Layout and MainWindow
- Tree
- DataTable
- Form
- ModalWindow
- Window
- TabWidget
- Toolbar
- Sidebar
- Chat
- Terminal
- CardPanel
- ResourceBoard
- File Transfer
- Message
- ContextMenu
- MenuBar
- Listbox
- Kanban
- ProgressBar
- Pagination
- Popup and tooltips
- Chart
- Scheduler
- MediaPlayer
Guides
Planning
Contributing