Skip to main content

Variable events

Service, database, and other variables expose callback events around each invoke(). Use them to validate input, change payloads, reshape response data before it reaches widgets, and react to success or failure on that variable only.

For where variable events sit alongside app, page, and UI events, see Event handling overview. For app-wide service failures, use App.onServiceError instead of duplicating the same logic on every variable.

Wire handlers in Studio

  1. Open the Variables dialog for the page or app.
  2. Select the variable (for example createEmployee).
  3. Open the Events tab and choose the event.
  4. Studio adds a handler in the page or app script, for example Page.createEmployeeonBeforeUpdate.

Handler names concatenate the variable name and event name: Page.{variableName}on{EventName}.

Which variables expose these events

Studio lists these callbacks on Service, Live, and Database CRUD variables, and on Login and Logout variables. In-memory Model variables and Device variables do not use this invoke lifecycle.

Invocation order

When you call invoke() on a service or live variable, handlers run in this order:

OrderEventPurpose
1onBeforeUpdateValidate or change input; return false to cancel the call
2onResultRun after any response (success or failure)
3onBeforeDatasetReadyTransform response data before dataSet is assigned
4aonSuccessRun only when the call succeeds and dataSet is updated
4bonErrorRun only when the call fails

onResult always runs when a response arrives. onSuccess and onError are mutually exclusive for that invocation.

To block a call before it starts, use onBeforeUpdate (return false) or configure In flight behavior on the variable.

onBeforeUpdate

Runs just before the variable calls the service. Validate or change inputData. Return false to cancel the call.

Page.createEmployeeonBeforeUpdate = function (variable, inputData, options) {
if (!inputData.employeeName) {
App.Actions.notify({
message: "Employee name is required",
severity: "error"
});
return false;
}
inputData.createdDate = new Date();
return true;
};
info

Database CRUD variables use specialized before-events instead of onBeforeUpdate:

  • READonBeforeListRecords
  • UPDATEonBeforeUpdateRecord
  • INSERTonBeforeInsertRecord
  • DELETEonBeforeDeleteRecord

Other variable types use onBeforeUpdate.

onBeforeDatasetReady

Runs after the service returns and before the variable dataSet is updated. Return the data shape you want bound to lists, forms, and other widgets.

Page.createEmployeeonBeforeDatasetReady = function (variable, data) {
let selectedDeviceIds = Page.Widgets.DevicePicker.selecteddevices
.map(device => device.id);

return data.filter(emp =>
selectedDeviceIds.includes(emp.devicesMappedId)
);
};

onResult

Runs when the service returns, whether the call succeeded or failed. Use it to normalize shape (for example wrap a single object in an array for a list).

Page.createEmployeeonResult = function (variable, data, operation) {
if (data && !Array.isArray(data)) {
variable.dataSet = [data];
}
};

onSuccess

Runs after a successful call, once dataSet is updated.

Page.createEmployeeonSuccess = function (variable, data, operation) {
App.Actions.notify({
message: "Employee created successfully",
severity: "success"
});
Page.Variables.getEmployees.invoke();
Page.Widgets.editEmployeeDialog.close();
};

onError

Runs when the variable call fails. Handle errors for this variable here; use App.onServiceError when the same handling should apply to every service in the app.

Page.createEmployeeonError = function (variable, error, operation) {
App.Actions.notify({
message: error.message || "Unable to create employee",
severity: "error"
});

if (error.details && error.details.validationErrors) {
Page.Widgets.employeeForm.setErrors(error.details.validationErrors);
}
};