All documentation
Developer
JavaScript events
Frontend extension points dispatched by Gravity Tables. Hook into them with vanilla JS or jQuery.
The frontend dispatches a small, stable set of CustomEvents on the table wrapper. Subscribe with addEventListener (or jQuery’s on()) to extend behaviour without forking.
All events bubble. Listen on the document for global handlers, or on a specific [data-gt-table] element for table-specific ones.
Lifecycle events#
gt:ready#
Dispatched once after a table finishes its initial render and is fully interactive (toolbar wired, filters bound, hydration complete).
document.addEventListener('gt:ready', (e) => {
console.log('Table', e.detail.tableId, 'is ready');
});
e.detail: { tableId, rowCount }
gt:refresh-start / gt:refresh-end#
Fires when an auto-refresh cycle begins and ends.
document.addEventListener('gt:refresh-start', (e) => {
document.getElementById('badge').classList.add('is-loading');
});
document.addEventListener('gt:refresh-end', (e) => {
document.getElementById('badge').classList.remove('is-loading');
});
gt:refresh-end’s e.detail: { tableId, rowCount, durationMs, success }
Edit events#
gt:edit-start#
Fires when a cell becomes editable (after a click).
document.addEventListener('gt:edit-start', (e) => {
const { entryId, fieldId, currentValue } = e.detail;
});
gt:edit-commit#
Fires after a successful inline edit save.
document.addEventListener('gt:edit-commit', (e) => {
const { entryId, fieldId, oldValue, newValue } = e.detail;
// Push to a dataLayer, sync to a third-party CRM, etc.
});
gt:edit-reject#
Fires when an edit fails validation. The cell rolls back automatically; this event is for telemetry.
document.addEventListener('gt:edit-reject', (e) => {
const { entryId, fieldId, attemptedValue, reason } = e.detail;
});
Filter / search events#
gt:filter-change#
Fires when any filter (column, search, sort) changes.
document.addEventListener('gt:filter-change', (e) => {
const { tableId, filters, search, sort } = e.detail;
});
Useful for syncing filter state to the URL bar:
document.addEventListener('gt:filter-change', (e) => {
const url = new URL(window.location);
url.searchParams.set('q', e.detail.search);
history.replaceState(null, '', url);
});
Bulk events#
gt:bulk-action#
Fires when a bulk action completes.
document.addEventListener('gt:bulk-action', (e) => {
const { action, entryIds, succeeded, failed } = e.detail;
});
Export events#
gt:export-start / gt:export-complete#
Fires at the start and end of an export request.
document.addEventListener('gt:export-complete', (e) => {
const { format, rowCount, fileSize, downloadUrl } = e.detail;
});
Querying state#
In addition to events, every table exposes a small read-only API on its wrapper element:
const table = document.querySelector('[data-gt-table="42"]');
const state = table.gtState; // { filters, search, sort, page, perPage, rowCount, isLoading }
For a programmatic refresh:
table.dispatchEvent(new CustomEvent('gt:request-refresh'));
Loading after page load#
If you’re injecting tables dynamically (e.g., after a page transition), call:
window.GravityTables?.init();
This re-scans the DOM for [data-gt-table] elements that haven’t been initialised yet.
Related#
- PHP hooks, server-side extension points
- Troubleshooting