Components
The Tray Javascript classCopy
To interact with the slots in the javascript code, you need to use the Tray javascript class. This class comprises the following:
Events: these allow you to listen to the load and change events of each slot in the wizard.
Functions: these allow you to interact with the Tray system and extend the functionality of your code.
Environment variables: these allow you to define a set of variables in the code editor, allowing you to abstract the code.
The slot stateCopy
The purpose of Custom JS code is to modify the state of a slot.
Each event is invoked with a set of arguments that describes the different states that you need to listen to.
In the javascript code you either return nothing (maintain the current slot state) or you return a new slot state.
The slot state is a javascript object that comprises the following properties:
externalId: the external ID of the slot, which matches what you can find in the slot's settings
jsonSchema: the schema that defines how the slot should be rendered in the wizard. Follows the JSON schema standard that you can learn more about here: https://json-schema.org/understanding-json-schema/
status: the status of the slot - one of HIDDEN , LOADING , VISIBLE . When a slot is first mounted on to a screen (loaded), it's status is always LOADING .
value: the value of the slot
validation: an object that can be specified in order to throw an error message and block the user from proceeding past the current config wizard screen. When specified as an empty object (default) or undefined no error message will be shown.
className: set a custom class name for the slot. You can use this when defining CSS rules to change the style of the slot.
The state schema is defined as follows in Tray (denoted by JavascriptConfigItemResult):
1type JavascriptConfigItemResult {2status: 'loading' | 'hidden' | 'visible';3className ? : string;4validation: SlotValidation;5jsonSchema: TraySchema7;6value: any; // Config slot value7}8type SlotValidation = {9status: 'ERROR';10message: string;11};
Here is an example state that you could expect to see:
1{2"externalId": "external_salesforce_object",3"jsonSchema": {4"type": "string"5},6"status": "VISIBLE",7"value": "First name",8"validation": {9"status": "ERROR",10"message": "First name is not a valid value for this field"11}12}
Tray eventsCopy
A note on events: let's say we have a screen where we have two config slots, and on the second slot we have enabled custom javascript. The script for the second slot will listen to events occurring in all slots on the same screen. In this way, you can define dependencies between slots on the same screen (see example for Showing/hiding slots based on dependencies)
The
CONFIG_SLOT_MOUNT
event is fired when a config slot has loaded onto the screen.The
CONFIG_SLOT_VALUE_CHANGED
event is fired when the value of a config slot has been changed.The
CONFIG_SLOT_STATUS_CHANGED
event is fired when the status of a config slot has been changed. (example HIDDEN to VISIBLE)The
AUTH_SLOT_MOUNT
event is fired when an auth slot has loaded onto the screen.The
AUTH_SLOT_VALUE_CHANGED
event is fired when the value of an auth slot has been changed, i.e. a new authentication has been selected.
When the custom javascript is enabled on a slot for the first time, you will notice an example implementation is prefilled that implements the CONFIG_SLOT_MOUNT
event.
Event argumentsCopy
Each event is invoked with an object argument that contains the following properties:
1 - event: contains information about the type of event that has fired, as well as data about the state of the slot for which the event fired.
For example, the slot for the salesforce object shown above with external ID external_slot_id
will fire the CONFIG_SLOT_MOUNT
event when first rendered on a screen. The value of the event would look something like the following:
1{2"type": "CONFIG_SLOT_MOUNT",3"data": {4"externalId": "external_salesforce_object",5"jsonSchema": {6"type": "string"7},8"status": "LOADING"9}10}
2 - previousSlotState: contains information about the state of the slot before the current event is fired.
This is most useful when listening to changes in other slots, as this property will contain the current schema of the slot on which the javascript is implemented.
The example below shows how this is used in practice. The value of this is the slot's state schema, so in this example where the slot is mounted and no schema has been set, this would be:
1{2"externalId": "external_salesforce_object",3"jsonSchema": {},4"status": "LOADING"5}
3 - previousWizardState:
Contains information about the state of the whole config wizard, including all previous pages.
This is most useful when the rendering of a new slot state depends on the values of previous config and auth slots in the wizard.
For instance, you can access the ID of an auth that has been created by the user for a service in order to dynamically fetch data via API calls and display values to the user as dropdowns (Check example). This property has the following schema (denoted by EmbeddedState):
1type EmbeddedState {2currentScreen: {3index: number;4status: 'loading' | 'visible';5};6values: {7[slotExternalId: string]: any8}9validation: {10[slotExternalId: string] ? : SlotValidation11}12}13type SlotValidation = {14status: 'error';15message: string;16};
Here's an example for our use case of the previousWizardState when the external_acme_object slot mounts and it's the second slot in the wizard:
1{2"currentScreen": {3"index": 1,4"status": "VISIBLE"5},6"values": {7"external_acme_object": "Contact"8},9"validation": {}10}
The slot could also be an auth slot, in which case its value is the ID of the authentication that has been created for the end user in Tray:
1{2"currentScreen":{3"index":1,4"status":"VISIBLE"5},6"values":{7"external_acme_authentication":"asc88xxxxx723"8},9"validation":{}10}
Tray functionsCopy
The tray class currently supports the following function:
callConnector: a wrapper around the GraphQL API mutation callConnector that can be invoked without requiring an API key, to call any Tray connector operation that you can find in the workflow builder.
This function will return a promise that will resolve to the output of the connector call. You can find more information on the API mutation here.
Here is an example of invoking this function in the javascript body to fetch information from Salesforce:
1// in this example we assume that we have an authentication slot for Salesforce with external ID external_salesforce_authentication2const authId = previousWizardState.values.external_salesforce_authentication;3const fetchSalesforceAccountFields = await tray.callConnector({4connector: 'salesforce',5version: '7.5',6operation: 'so_object_describe',7authId,8input: {9object: "Account"10}11});
Unlike the API mutation callConnector, the input does not need to be JSON stringified before sending to the request.
Config wizard environment variablesCopy
Config wizard environment variables allow you to define a set of variables in the code editor, allowing you to abstract the code. You can set them inside the code editor, and then reference them through the tray class in the code under the key env.
An example of this is, By default the editor is set up with the environment variable "slotExternalId" - which you can use to refer to the external ID of the slot you are currently writing code for in the editor. You can access this environment variable in your code with the property tray.env.slotExternalId
1const slot_external_id = tray.env.slotExternalId;
You can define environment variables in the right-hand panel of the javascript code editor:
Which you can use to reference previously set external variables: