Repository navigation
api_events
- bulkActionComplete
- bulkActionError
- columnsReordered
- formClosed
- formCreated
- recordAdded
- recordDeleted
- recordsLoaded
- recordUpdated
- selectionChanged
FTable uses a custom event handling system. You can listen for events in two ways:
Any event is just an option:
const table = new FTable('#MyTableContainer', {
// ... other options
formClosed: function(eventArgs) {
// Handle form closed event
},
recordAdded: function(eventArgs) {
// Handle record added event
}
// ... other event handlers
});Only these events are recognized as configuration options: formCreated, formClosed, recordsLoaded, recordAdded, recordUpdated, recordDeleted, selectionChanged, bulkActionComplete and bulkActionError. All other events (e.g. columnsReordered) can only be registered with table.on().
const table = new FTable('#MyTableContainer', { /*...*/ });
table.on('recordAdded', function(eventArgs) {
// Handle record added event
});or, if you want it to run only once:
const table = new FTable('#MyTableContainer', { /*...*/ });
table.once('recordAdded', function(eventArgs) {
// Handle record added event
});And to remove a listener you must pass the same callback function you registered (calling table.off('recordAdded') without a callback removes nothing):
const table = new FTable('#MyTableContainer', { /*...*/ });
function onRecordAdded(eventArgs) {
// Handle record added event
}
table.on('recordAdded', onRecordAdded);
// later...
table.off('recordAdded', onRecordAdded);FTable also provides a convenient function to wait for dependant fields to be ready. 2 examples, both used in formCreated:
function _getQueryParams(qs) {
qs = qs.split('+').join(' ');
let params = {}, tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while ((tokens = re.exec(qs))) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
const $_GET = _getQueryParams(document.location.search);
// New incident for specific asset
if ($_GET['new_inc_for_asset']) {
const asset_nummer = $_GET['new_inc_for_asset'];
table.once('formCreated', async (e) => {
await FTable.waitForFieldReady('asset_id', e.form);
const assetSelect = e.form.querySelector('[name="asset_id"]');
const optionElement = [...assetSelect.querySelectorAll('option')]
.find(opt => opt.textContent.trim() === asset_nummer.trim());
if (optionElement) {
assetSelect.value = optionElement.value;
assetSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
});
table.showAddRecordForm();
} // When class_id changes, wait for user_id to reload
const classIdSelect = data.form.querySelector('select[name="class_id"]');
classIdSelect.addEventListener('change', async () => {
// user_id will now be repopulated → wait for it again
await FTable.waitForFieldReady('user_id', data.form);
updateWarrantyWarning();
});This event is raised after a bulk action has been successfully processed: the table has been reloaded and the "Apply" button has been restored.
-
eventArgs.data: The parsed response of the bulk action request (e.g.
{ Result: 'OK', Message: '...' }). - eventArgs.doAction: The action value that was executed.
- eventArgs.ids: Array of the processed record keys.
- eventArgs.selectedRows: Array of the selected row elements.
Note: the table has been reloaded before this event is emitted, so the selectedRows elements are the rows of the previous render - use table.getSelectedRows() if you need the current ones. eventArgs does not contain a table reference.
const table = new FTable('#MyTableContainer', {
// ... other options
bulkActionComplete: function(eventArgs) {
const msg = document.getElementById('message');
if (msg) msg.innerHTML = eventArgs.data.Message;
}
});This event is raised when a bulk action request fails (e.g. a server or network error). The "Apply" button is restored before this event is emitted.
- eventArgs.error: The error object/exception.
- eventArgs.doAction: The action value that was attempted.
- eventArgs.ids: Array of the selected record keys.
- eventArgs.selectedRows: Array of the selected row elements.
const table = new FTable('#MyTableContainer', {
// ... other options
bulkActionError: function(eventArgs) {
console.error('Bulk action failed:', eventArgs.error);
}
});This event is raised when an edit or create form dialog is closed.
- eventArgs.form: The form as a DOM element.
-
eventArgs.formType: Can be
'edit'or'create'. -
eventArgs.record: Always
null- the record is not passed on close. Read the values fromeventArgs.forminstead.
const table = new FTable('#MyTableContainer', {
// ... other options
formClosed: function(eventArgs) {
console.log('Form closed:', eventArgs.formType);
if (eventArgs.formType === 'edit') {
console.log('Edited row:', eventArgs.record);
}
}
});This event is raised when an edit or create form is created for a record.
- eventArgs.form: The form as a DOM element.
-
eventArgs.formType: Can be
'edit'or'create'. -
eventArgs.record: The record the form was opened for (edit form, or a prefilled record for create/clone).
nullwhen a plain "add new record" form was opened.
const table = new FTable('#MyTableContainer', {
// ... other options
formCreated: function(eventArgs) {
console.log('Form created:', eventArgs.formType);
if (eventArgs.formType === 'edit') {
console.log('Editing record:', eventArgs.record);
}
// You can modify the form after it's created
const nameField = eventArgs.form.querySelector('[name="Name"]');
if (nameField) {
nameField.style.backgroundColor = '#f0f0f0';
}
}
});This event is raised when a user successfully creates and saves a new record.
- eventArgs.record: The added record.
const table = new FTable('#MyTableContainer', {
// ... other options
recordAdded: function(eventArgs) {
console.log('New record added:', eventArgs.record);
// Show a custom notification
alert('Record "' + eventArgs.record.Name + '" has been added successfully!');
}
});This event is raised when a record is successfully deleted through the delete confirmation (deleteRecord).
Note: bulk deletes (deleteRows) do not emit this event.
- eventArgs.record: The deleted record.
const table = new FTable('#MyTableContainer', {
// ... other options
recordDeleted: function(eventArgs) {
console.log('Record deleted:', eventArgs.record);
// Log the deletion
console.log('Deleted record with ID:', eventArgs.record.PersonId);
}
});This event is raised when FTable loads records from the server and refreshes the table.
- eventArgs.records: All records loaded from the server.
- eventArgs.serverResponse: The response JSON object returned from the server.
const table = new FTable('#MyTableContainer', {
// ... other options
recordsLoaded: function(eventArgs) {
console.log('Records loaded:', eventArgs.records.length + ' records');
console.log('Server response:', eventArgs.serverResponse);
// Update a counter or status display
const statusElement = document.getElementById('recordCount');
if (statusElement) {
statusElement.textContent = 'Showing ' + eventArgs.records.length + ' records';
}
}
});This event is raised when a user successfully updates a record.
- eventArgs.record: The updated record.
- eventArgs.row: The updated table row.
const table = new FTable('#MyTableContainer', {
// ... other options
recordUpdated: function(eventArgs) {
console.log('Record updated:', eventArgs.record);
console.log('Updated row:', eventArgs.row);
// Highlight the updated row temporarily
eventArgs.row.style.backgroundColor = '#ffffcc';
setTimeout(function() {
eventArgs.row.style.backgroundColor = '';
}, 2000);
}
});This event is raised when the selected rows on the table change.
- eventArgs.selectedRows: Array of currently selected row elements.
- Uses the
getSelectedRows()method to get the selected rows programmatically.
const table = new FTable('#MyTableContainer', {
// ... other options
selecting: true,
selectionChanged: function(eventArgs) {
console.log('Selection changed. Selected rows:', eventArgs.selectedRows.length);
// Enable/disable bulk action buttons based on selection
const deleteButton = document.getElementById('bulkDeleteButton');
if (deleteButton) {
deleteButton.disabled = eventArgs.selectedRows.length === 0;
}
// Show selected record details
if (eventArgs.selectedRows.length === 1) {
const record = eventArgs.selectedRows[0].recordData;
console.log('Selected record:', record);
}
}
});This event is raised when the column order has changed (drag-and-drop reorder or reorderColumnsByName). It cannot be used as a configuration option, register it with table.on().
- eventArgs.sourceField: The field name of the moved column.
- eventArgs.targetField: The field name of the column it was dropped on.
-
eventArgs.insertAfter:
truewhen the column was placed after the target column. - eventArgs.columnList: The new column order (array of field names).
const table = new FTable('#MyTableContainer', { /*...*/ });
table.on('columnsReordered', function(eventArgs) {
console.log('New column order:', eventArgs.columnList);
});Always include error handling in your event handlers:
const table = new FTable('#MyTableContainer', {
recordAdded: function(eventArgs) {
try {
// Your event handling code here
console.log('Record added:', eventArgs.record);
} catch (error) {
console.error('Error in recordAdded event handler:', error);
}
}
});For events that fire frequently (like selectionChanged), consider debouncing:
let selectionTimeout;
const table = new FTable('#MyTableContainer', {
selectionChanged: function(eventArgs) {
clearTimeout(selectionTimeout);
selectionTimeout = setTimeout(function() {
// Debounced selection handling
updateSelectionUI(eventArgs.selectedRows);
}, 100);
}
});If you're dynamically creating/destroying tables, make sure to clean up event handlers to prevent memory leaks:
// When destroying a table
table.destroy(); // This should clean up internal event handlers
// Clean up any external references
table = null;