Events
When working with complex data, it can often be useful to perform some additional action when Editor updates the database based on information from the client-side. Consider for example the following use case:
- Modifying the Editor instance or form fields based on that action being taken
- Deleting files from the file system when rows are removed
- Logging information to a database about an action that a user has taken.
to name just a few!
To make this possible, the Node.JS Editor
class provides an event listener / callback option similar to the events that the client-side Javascript will trigger.
Listening for events
Events listeners can be added using the Editor.on()
method which takes two arguments:
- The event name to listen for
- A callback function which defines the action to take. The arguments passed to the callback are event dependent. The return value for the
pre*
named events can be used to cancel actions (see below), while the other event handlers to not use any returned value.
Multiple listeners for the same event can be added simply by calling the Editor.on()
method multiple times. The events will be executed in the same sequence that they were added.
Available events
The Editor
class will trigger the following events - the arguments passed into the function are also documented (please note that the events are shown below in the order that they are triggered for each action):
Get
preGet
(cancellable) - Triggered immediately prior to reading row data from the databaseeditor
- The Editor instance that triggered the eventid
- Row id being selected if only a single row is to be selected (i.e. after an edit). Otherwise this value will benull
indicating that all rows will be selected.
postGet
- Triggered immediately after row information has been read from the databaseeditor
- The Editor instance that triggered the eventid
- Row id being selected if only a single row is to be selected (i.e. after an edit). Otherwise this value will benull
indicating that all rows will be selected.data
- Data array of rows that have been read from the database
Create
preCreate
(cancellable) - Triggered prior to creating a new row and before validation has occurred, allowing extra validation to be added or values to be seteditor
- The Editor instance that triggered the eventvalues
- The values submitted by the client-side
validatedCreate
- Triggered immediately prior to creating a new row, after validation has occurred (since 1.9.3)editor
- The Editor instance that triggered the eventvalues
- The values submitted by the client-side
writeCreate
- Data has been written to the database, but not yet read back, allowing the database to be updated before the data is gathered to display in the tableeditor
- The Editor instance that triggered the eventid
- ID of the row that was createdvalues
- The values submitted by the client-side
postCreate
- Triggered immediately after a new row has been creatededitor
- The Editor instance that triggered the eventid
- ID of the newly created rowvalues
- The values submitted by the client-side$row
- The newly created row's data, as read from the database
Edit
preEdit
(cancellable) - Triggered prior to updating an existing row and before validation has occurrededitor
- The Editor instance that triggered the eventid
- ID of the row to be editedvalues
- The values submitted by the client-side
validatedEdit
- Triggered immediately prior to updating an existing row, after validation has occurred (since 1.9.3)editor
- The Editor instance that triggered the eventid
- ID of the row to be editedvalues
- The values submitted by the client-side
writeEdit
- Data has been written to the database, but not yet read back, allowing the database to be updated before the data is gathered to display in the tableeditor
- The Editor instance that triggered the eventid
- ID of the row to be editedvalues
- The values submitted by the client-side
postEdit
- Triggered immediately after an existing row has been updatededitor
- The Editor instance that triggered the eventid
- ID of the row that has been editedvalues
- The values submitted by the client-side$row
- The updated row's data, as read from the database
Remove
preRemove
(cancellable) - Triggered immediately prior to deleting an existing roweditor
- The Editor instance that triggered the eventid
- ID of the row to be deletedvalues
- The values submitted by the client-side (i.e. the row's data set)
postRemove
- Triggered immediately after a row has been deletededitor
- The Editor instance that triggered the eventid
- ID of the row that has been deletedvalues
- The values submitted by the client-side (i.e. the row's data set)
Upload
preUpload
(cancellable) - Triggered immediately prior to a file upload being processededitor
- The Editor instance that triggered the eventdata
- Data submitted by the upload form
postUpload
- Triggered after a file has been uploaded and information about it read from the databaseeditor
- The Editor instance that triggered the eventid
- ID of the database record for the uploaded file (or the file's unique name if a database record is not used)files
- The file information that has been read from the databasedata
- Data submitted by the upload form
Please note that for multi-row creation, editing and deletion, the events are triggered once for each row.
Cancellable events
The pre*
events are all cancellable, allowing the server-side process to optionally decide if a row should be processed or not. This can be useful as a form of data validation, disallowing users from certain actions (although please note that this is not a replacement for validation - no error will be shown to the end user if the processing of a row is cancelled!).
To cancel the processing of a row return false
from the event handler. Any other rows that were also submitted, which are not cancelled themselves, will be correctly processed and the client-side table appropriately updated.
Examples
Modifying fields
It is quite common to wish to store information in the database that is not directly settable by the end user, and furthermore, to have different information stored based on the action that has been triggered from the client-side. This can easily be achieved with events and the methods of the Field
class.
Consider the case where we have information about the user who is using the session available in a session variable (req.session.user_id
). We wish to store in the database this information for who created the entry and who last updated the item.
This can be achieved using the preCreate
and preEdit
methods:
Controller:
router.all('/api/staff', async function(req, res) {
let editor = new Editor(db, 'staff')
.fields(
new Field( 'first_name' ),
new Field( 'last_name' ),
new Field( 'position' ),
new Field( 'email' ),
new Field( 'created_by' ).set( Field.SetType.Create ),
new Field( 'last_updated' )
)
.on( 'preCreate', (editor, values) => {
editor
.field( 'created_by' )
.setValue( req.session.user_id );
} )
.on( 'preEdit', (editor, id, values) => {
editor
.field( 'last_updated' )
.setValue( new Date().toISOString() );
} );
await editor.process(req.body);
res.json(editor.data());
});
- Line 1 - Express router for the
/api/staff
URL (you don't need to use Express, use anything you want!) - Lines 2-8 - Simple Editor initialisation with six fields. Note that
created_by
is configured to be writeable only for a create action. - Line 9 - Listen for the
preCreate
event - Line 10 - Get the
created_by
field to modify it - Line 11 - Set the field so that it will be written only on the create action
- Line 12 - Set the value to write to the database to be the session variable of interest.
- Line 14 - Listen for the
preEdit
event (note it has different parameters topreCreate
) - Lines 15-17 - Set the
last_updated
value to the current time on edit.
Logging changes
As a further example of how to use the events emitted by Editor, consider the case where we want to log information to a database table that details what user made a change, what the change was and when. For this we can use use either the pre*
or post*
events, but we will use the post*
events here which ensures that data is logged only if it was successfully inserted into the database.
Consider the following code:
function logChange( action, id, values, session ) {
db.insert( 'staff-log', {
user: session.user_id,
action: action,
values: JSON.stringify( values ),
row: id,
when: new Date().toISOString()
} );
}
router.all('/api/staff', async function(req, res) {
let editor = new Editor(db, 'staff')
.fields(
new Field( 'first_name' ),
new Field( 'last_name' ),
new Field( 'position' ),
new Field( 'email' )
)
.on( 'postCreate', (editor, id, values, row) => {
logChange( 'create', id, values, req.session );
} )
.on( 'postEdit', (editor, id, values, row) => {
logChange( 'edit', id, values, req.session );
} )
.on( 'postRemove', (editor, id, values) => {
logChange( 'delete', id, values, req.session );
} )
await editor.process(req.body);
res.json(editor.data());
});
- Lines 1-9 -
logChange
function which will insert a row into the logging table using the Knex.JSinsert
method. - Line 11 - Express router. Again, any router could be used, Express is used for convenience here.
- Lines 19-25 - Attach event listeners to
postCreate
,postEdit
andpostRemove
which will calllogChange
with suitable arguments.
Node.JS API documentation
The Node.JS API developer documentation for the Editor Node.JS classes is available for detailed and technical discussion about the methods and classes discussed above.