Skip to content

Event Reference

Complete reference for all PyWry events, payloads, and the JavaScript bridge API.

Event Format

All events follow the namespace:event-name pattern:

Part Rules Examples
namespace Starts with letter, alphanumeric app, plotly, grid, myapp
event-name Starts with letter, alphanumeric + hyphens click, row-select, update-data

Reserved namespaces: pywry:*, plotly:*, grid:*, toolbar:*, auth:*


System Events (pywry:*)

Lifecycle Events (JS → Python)

Event Payload Description
pywry:ready {} Window/widget initialized and ready
pywry:result any Data from window.pywry.result(data)
pywry:message any Data from window.pywry.message(data)
pywry:content-request {widget_type, window_label, reason} Window requests content
pywry:disconnect {} Widget disconnected (browser/inline mode)
pywry:close {label} Window close requested

Window Events (JS → Python)

Event Payload Description
window:closed {label} Window was closed
window:hidden {label} Window was hidden

Content & Styling (Python → JS)

Event Payload Description
pywry:set-content {id?, selector?, text?, html?} Update element text/HTML
pywry:set-style {id?, selector?, styles: {}} Update element CSS
pywry:inject-css {css, id?} Inject CSS (id for replacement)
pywry:remove-css {id} Remove injected CSS by id
pywry:update-html {html} Replace entire page content
pywry:update-theme {theme} Switch theme (dark or light)

Notifications & Actions (Python → JS)

Event Payload Description
pywry:alert {message, type?, title?, duration?, position?, callback_event?} Toast notification
pywry:download {content, filename, mimeType?} Trigger file download
pywry:navigate {url} Navigate to URL
pywry:refresh {} Request content refresh
pywry:cleanup {} Cleanup resources (native mode)

Alert types: info, success, warning, error, confirm

Alert positions: top-right (default), top-left, bottom-right, bottom-left


Plotly Events (plotly:*)

User Interactions (JS → Python)

Event Payload
plotly:click {chartId, widget_type, points, point_indices, curve_number, event}
plotly:hover {chartId, widget_type, points, point_indices, curve_number}
plotly:unhover {chartId}
plotly:selected {chartId, widget_type, points, point_indices, range, lassoPoints}
plotly:deselect {chartId}
plotly:relayout {chartId, widget_type, relayout_data}
plotly:state-response {chartId, layout, data}
plotly:export-response {data: [{traceIndex, name, x, y, type}, ...]}

Point structure:

{
    "curveNumber": 0,
    "pointNumber": 5,
    "pointIndex": 5,
    "x": 2.5,
    "y": 10.3,
    "z": None,
    "text": "label",
    "customdata": {...},
    "data": {...},
    "trace_name": "Series A"
}

Chart Updates (Python → JS)

Event Payload
plotly:update-figure {figure, chartId?, config?, animate?}
plotly:update-layout {layout, chartId?}
plotly:update-traces {update, indices, chartId?}
plotly:replace {figure, chartId?}
plotly:reset-zoom {chartId?}
plotly:request-state {chartId?}
plotly:export-data {chartId?}

AG Grid Events (grid:*)

User Interactions (JS → Python)

Event Payload
grid:row-selected {gridId, widget_type, rows}
grid:cell-click {gridId, widget_type, rowIndex, colId, value, data}
grid:cell-double-click {gridId, widget_type, rowIndex, colId, value, data}
grid:cell-edit {gridId, widget_type, rowIndex, rowId, colId, oldValue, newValue, data}
grid:filter-changed {gridId, widget_type, filterModel}
grid:sort-changed {gridId, widget_type, sortModel}
grid:data-truncated {gridId, widget_type, displayedRows, truncatedRows, message}
grid:mode {gridId, widget_type, mode, serverSide, totalRows, blockSize, message}
grid:request-page {gridId, widget_type, startRow, endRow, sortModel, filterModel}
grid:state-response {gridId, columnState, filterModel, sortModel, context?}
grid:export-csv {gridId, data}

Grid Updates (Python → JS)

Event Payload
grid:update-data {data, gridId?, strategy?}
grid:update-columns {columnDefs, gridId?}
grid:update-cell {rowId, colId, value, gridId?}
grid:update-grid {data?, columnDefs?, restoreState?, gridId?}
grid:request-state {gridId?, context?}
grid:restore-state {state, gridId?}
grid:reset-state {gridId?, hard?}
grid:update-theme {theme, gridId?}
grid:page-response {gridId, rows, totalRows, isLastPage, requestId}
grid:show-notification {message, duration?, gridId?}

Update strategies for grid:update-data: set (default — replace all), append, update


Toolbar Events (toolbar:*)

User Interactions (JS → Python)

Event Payload
toolbar:collapse {componentId, collapsed: true}
toolbar:expand {componentId, collapsed: false}
toolbar:resize {componentId, position, width, height}
toolbar:state-response {toolbars, components, timestamp, context?}

State Management (Python → JS)

Event Payload
toolbar:request-state {toolbarId?, componentId?, context?}
toolbar:set-value {componentId, value?, label?, disabled?, ...attrs}
toolbar:set-values {values: {id: value, ...}, toolbarId?}

Supported attributes for toolbar:set-value:

Attribute Description
value Component value
label / text Text content
disabled Enable/disable
variant Button style (primary, danger, etc.)
tooltip / description Hover text
options Dropdown options
style Inline CSS (string or object)
className CSS classes ({add: [...], remove: [...]})
placeholder, min, max, step Input constraints

Marquee Events (Python → JS)

Event Payload
toolbar:marquee-set-content {id, text?, html?, speed?, paused?, separator?}
toolbar:marquee-set-item {ticker, text?, html?, styles?, class_add?, class_remove?}

Auth Events (auth:*)

The auth:* namespace is used by the built-in OAuth2 authentication system. Events flow in both directions: the frontend can request login/logout, and the backend notifies the frontend when auth state changes (e.g. after a token refresh or successful logout).

Availability

Auth events are only active when PYWRY_DEPLOY__AUTH_ENABLED=true and a valid PYWRY_OAUTH2__* configuration is present. In native mode the full flow is handled by app.login() / app.logout() — these events apply to the frontend integration via window.pywry.auth.

Auth Requests (JS → Python)

Event Payload Description
auth:login-request {} Frontend requests a login flow (calls window.pywry.auth.login()). In native mode the backend opens the provider's authorization URL; in deploy mode it redirects to /auth/login.
auth:logout-request {} Frontend requests logout (calls window.pywry.auth.logout()). The backend revokes tokens, destroys the session, and emits auth:logout back.

Auth Notifications (Python → JS)

Event Payload Description
auth:state-changed {authenticated, user_id?, roles?, token_type?} Auth state changed (login succeeded or session expired). When authenticated is false, window.__PYWRY_AUTH__ is cleared.
auth:token-refresh {token_type, expires_in?} Access token was refreshed in the background. Updates the current session without requiring re-login.
auth:logout {} Server-side logout completed. Clears window.__PYWRY_AUTH__ and notifies registered onAuthStateChange handlers.

auth:state-changed payload detail:

{
    "authenticated": True,
    "user_id": "user@example.com",   # sub / id / email from userinfo
    "roles": ["viewer", "editor"],   # from session roles list
    "token_type": "Bearer"           # OAuth2 token type
}

When authenticated is false only the key itself is present:

{"authenticated": False}

Component Event Payloads

Every toolbar component emits its custom event with these payloads:

Component Payload
Button {componentId, ...data}
Select {value, componentId}
MultiSelect {values, componentId}
TextInput {value, componentId}
TextArea {value, componentId}
SearchInput {value, componentId}
SecretInput {value, componentId}
NumberInput {value, componentId}
DateInput {value, componentId} (YYYY-MM-DD format)
SliderInput {value, componentId}
RangeInput {start, end, componentId}
Toggle {value, componentId} (boolean)
Checkbox {value, componentId} (boolean)
RadioGroup {value, componentId}
TabGroup {value, componentId}

JavaScript API

The window.pywry Object

Every PyWry window/widget exposes a global bridge object:

window.pywry = {
    emit(event, data),      // Send event to Python
    on(event, handler),     // Listen for events from Python
    off(event, handler),    // Remove event listener
    result(data),           // Send result to Python (triggers pywry:result)
    message(data),          // Send message to Python (triggers pywry:message)
    label,                  // Current window/widget label
    config,                 // Widget configuration
    version,                // PyWry version string
};

Sending Events to Python

window.pywry.emit("app:save", { id: 123 });

window.pywry.emit("app:update", {
    selection: [1, 2, 3],
    timestamp: Date.now(),
    metadata: { source: "user" }
});

Listening for Python Events

// Register handler
window.pywry.on("app:data-ready", function(data) {
    console.log("Data:", data);
});

// Remove handler
window.pywry.off("app:update", handler);

Chart, Grid, and Toolbar Globals

// Plotly charts
window.__PYWRY_CHARTS__["chart-id"]       // DOM element

// AG Grid instances
window.__PYWRY_GRIDS__["grid-id"]         // {api, div}
window.__PYWRY_GRIDS__["grid-id"].api.getSelectedRows()

// Toolbar state
window.__PYWRY_TOOLBAR__.getState()                     // All toolbars
window.__PYWRY_TOOLBAR__.getState("toolbar-id")         // Specific toolbar
window.__PYWRY_TOOLBAR__.getValue("component-id")       // Get value
window.__PYWRY_TOOLBAR__.setValue("component-id", value) // Set value

Auth Globals (window.pywry.auth)

When auth_enabled=True the auth-helpers.js script is injected and the window.pywry.auth namespace becomes available.

// Check authentication state
window.pywry.auth.isAuthenticated()   // boolean

// Get the full auth state
window.pywry.auth.getState()
// Returns: { authenticated, user_id, roles, token_type }

// Trigger OAuth2 login flow (emits auth:login-request to Python)
window.pywry.auth.login()

// Trigger logout (emits auth:logout-request to Python)
window.pywry.auth.logout()

// React to auth state changes (from auth:state-changed / auth:logout events)
window.pywry.auth.onAuthStateChange(function(state) {
    if (state.authenticated) {
        console.log("Logged in as", state.user_id, "with roles", state.roles);
    } else {
        console.log("Logged out");
    }
});

window.__PYWRY_AUTH__ is injected server-side for authenticated requests and contains { user_id, roles, token_type }. Use window.pywry.auth.getState() rather than reading it directly — the helper normalizes the value and handles the unauthenticated case.

Tauri Access (Native Mode Only)

In native desktop mode, a subset of Tauri APIs and the PyTauri IPC bridge are available via window.__TAURI__. PyWry does not expose the full Tauri plugin ecosystem — only the APIs listed below are bundled and configured.

Do not use window.__TAURI__.core.invoke()

PyWry uses PyTauri for all JS → Python IPC. Call window.__TAURI__.pytauri.pyInvoke() instead of the standard Tauri invoke(). All registered PyWry commands go through this path.

PyTauri Commands

All JS → Python communication uses pyInvoke:

if (window.__TAURI__ && window.__TAURI__.pytauri) {
    // Send a custom event to Python
    window.__TAURI__.pytauri.pyInvoke('pywry_event', {
        label: window.__PYWRY_LABEL__ || 'main',
        event_type: 'app:my-action',
        data: { key: 'value' }
    });

    // Return a result to Python
    window.__TAURI__.pytauri.pyInvoke('pywry_result', {
        data: { answer: 42 },
        window_label: window.__PYWRY_LABEL__ || 'main'
    });
}

Prefer window.pywry.emit()

You rarely need to call pyInvoke directly. The window.pywry.emit() bridge wraps it for you and works across all rendering modes.

Available Tauri APIs

API Namespace Used for
Event system window.__TAURI__.event Listening for Python → JS events (listen, emit)
Dialog window.__TAURI__.dialog Native save-file dialog (save())
Filesystem window.__TAURI__.fs Writing files to disk (writeTextFile())
PyTauri IPC window.__TAURI__.pytauri JS → Python calls (pyInvoke())

Example — native save dialog:

if (window.__TAURI__ && window.__TAURI__.dialog && window.__TAURI__.fs) {
    const filePath = await window.__TAURI__.dialog.save({
        defaultPath: 'export.csv',
        title: 'Save File'
    });
    if (filePath) {
        await window.__TAURI__.fs.writeTextFile(filePath, csvContent);
    }
}

Example — listening for Python events:

if (window.__TAURI__ && window.__TAURI__.event) {
    window.__TAURI__.event.listen('pywry:event', function(event) {
        // event.payload contains {type, data}
        console.log('Received:', event.payload.type, event.payload.data);
    });
}

Tauri APIs are only available in native desktop mode

Check for window.__TAURI__ before using any Tauri-specific API. In browser and notebook modes, only the window.pywry bridge is available — it abstracts the transport automatically.