Skip to main content

Actions Reference

Actions define behaviors triggered by user interactions or page lifecycle events in Aptean Mesh. They are declared inside the contract.actions array and referenced by id from components, the contract's initialAction/scanAction, or other actions.

Every action type shares a common base interface (IAction in the Kotlin source):

PropertyTypeDefaultDescription
idstringrequiredUnique identifier used to reference this action from components or other actions.
typestringrequiredType discriminator. Determines which action subtype is used.
confirmConfirmDialog?nullOptional confirmation dialog displayed before the action executes.
inputInputPrompt?nullOptional input prompt dialog to collect user input before the action executes.

The type field is the JSON discriminator (set via @SerialName in Kotlin). The client deserializes the action to the matching subclass based on this value.


ApiAction

Type discriminator: "api"

Calls a backend AL codeunit method via JSON-RPC. This is the primary action type for data operations -- fetching records, submitting changes, processing scans, and triggering business logic.

Properties

PropertyTypeDefaultDescription
idstringrequiredUnique action identifier.
typestringrequiredMust be "api".
methodstringrequiredThe RPC method name to invoke on the AL codeunit. Resolves to State.Method() in the service's State codeunit.
paramsstring[][]Parameter keys to extract from page data (navigation data, input values, filter selections) and pass to the method.
confirmConfirmDialog?nullConfirmation dialog shown before executing.
inputInputPrompt?nullInput prompt shown before executing.

How it connects to AL

When the client dispatches an ApiAction, it:

  1. Resolves each key in params from the current page data context (navigation parameters, input field values, filter selections).
  2. Sends a JSON-RPC request to the service identified by the page's service field.
  3. The AL codeunit reads parameters with State.GetInput('paramName') and returns data via State.SetValue(...) or State.SetArray(...).
  4. The client merges the response data into the page's data store, triggering UI updates on any bound components.

Example

{
"id": "loadOrders",
"type": "api",
"method": "GetOrders",
"params": ["locationFilter", "statusFilter"]
}

Example with confirmation and input

{
"id": "adjustQuantity",
"type": "api",
"method": "AdjustQuantity",
"params": ["ItemNo", "newQty"],
"confirm": {
"title": "Adjust Quantity",
"message": "Are you sure you want to change the quantity?",
"confirmLabel": "Adjust",
"cancelLabel": "Cancel"
},
"input": {
"title": "New Quantity",
"message": "Enter the adjusted quantity:",
"inputKey": "newQty",
"defaultValue": "",
"confirmLabel": "OK",
"keyboardType": "number"
}
}

Type discriminator: "navigate"

Navigates to another page within the App Bundle. Navigation is instant because all page definitions are cached locally after the initial GetPageFlow call.

Properties

PropertyTypeDefaultDescription
idstringrequiredUnique action identifier.
typestringrequiredMust be "navigate".
destinationstringrequiredThe pageId of the target page to navigate to.
dataobject{}Key-value pairs passed to the destination page as initial context. Values support {FieldName} interpolation from the current data context.
confirmConfirmDialog?nullConfirmation dialog shown before navigating.
inputInputPrompt?nullInput prompt shown before navigating.

Parameter interpolation

Use {FieldName} syntax in the data values to interpolate values from the current row or page data context. When a user taps a repeater row, the row's fields are available for interpolation:

{
"id": "onOrderTap",
"type": "navigate",
"destination": "ORDER-DETAIL",
"data": {
"OrderNo": "{Document No}",
"OrderType": "{Type}"
}
}

If the tapped row has "Document No": "WH-001" and "Type": "Pick", the destination page receives {"OrderNo": "WH-001", "OrderType": "Pick"}. The destination page's API actions can then include "OrderNo" in their params list, and AL reads it with State.GetInput('OrderNo').

Example

{
"id": "navigateToDetail",
"type": "navigate",
"destination": "ITEM-DETAIL",
"data": {
"ItemNo": "{No}",
"LocationCode": "{Location Code}"
}
}

FilterAction

Type discriminator: "filter"

Fetches filtered data from a backend endpoint. Used by filter controls (selector components, filter panel) to dynamically reload data when the user changes a filter selection.

Properties

PropertyTypeDefaultDescription
idstringrequiredUnique action identifier.
typestringrequiredMust be "filter".
endpointstringrequiredThe API endpoint (method name) to call with the current filter values.
paramsstring[][]Parameter keys whose current values are sent with the filter request. Typically these match the id values of filter definitions.
confirmConfirmDialog?nullConfirmation dialog shown before fetching.
inputInputPrompt?nullInput prompt shown before fetching.

How filter actions work

  1. A selector component or filter panel triggers the filter action via onSelect or a similar event.
  2. The client reads the current value of each key listed in params from the filter state.
  3. A request is sent to the endpoint with those parameter values.
  4. The response data replaces the page's data store, and bound components re-render.

Example

{
"id": "onStatusFilterChanged",
"type": "filter",
"endpoint": "GetOrders",
"params": ["StatusFilter", "LocationFilter"]
}

LookupAction

Type discriminator: "lookup"

Opens a lookup modal that lets the user search and select from a list of options. The lookup list is populated from a repeater component's data.

Properties

PropertyTypeDefaultDescription
idstringrequiredUnique action identifier.
typestringrequiredMust be "lookup".
titlestring?nullTitle text displayed in the lookup modal header.
componentIdstring?nullThe id of a repeater component whose data populates the lookup list.
confirmConfirmDialog?nullConfirmation dialog shown before opening the lookup.
inputInputPrompt?nullInput prompt shown before opening the lookup.

Example

{
"id": "selectWarehouse",
"type": "lookup",
"title": "Select Warehouse",
"componentId": "warehouseList"
}

ConfirmDialog

An optional confirmation dialog that can be attached to any action. When present, the client shows this dialog before executing the action. If the user cancels, the action is not executed.

PropertyTypeDefaultDescription
titlestringrequiredThe dialog title text.
messagestringrequiredThe dialog body message explaining what the action will do.
confirmLabelstring""Label for the confirm button. Falls back to a platform default ("Confirm") when blank.
cancelLabelstring""Label for the cancel button. Falls back to a platform default ("Cancel") when blank.

Example

{
"confirm": {
"title": "Delete Record",
"message": "This cannot be undone. Continue?",
"confirmLabel": "Delete",
"cancelLabel": "Keep"
}
}

InputPrompt

An optional input prompt dialog that can be attached to any action. When present, the client shows a text input dialog before executing the action. The user's input is stored under the specified inputKey and made available to the action's parameters.

PropertyTypeDefaultDescription
titlestringrequiredThe dialog title text.
messagestringrequiredThe dialog body message explaining what input is needed.
inputKeystringrequiredThe data key where the user's input value is stored for the action. Include this key in the action's params to pass it to AL.
defaultValuestring""Pre-filled value in the input field.
confirmLabelstring""Label for the confirm button. Falls back to a platform default when blank.
keyboardTypestring"text"Keyboard type to display. Common values: "text", "number".

Example

{
"id": "enterQuantity",
"type": "api",
"method": "SetQuantity",
"params": ["ItemNo", "enteredQty"],
"input": {
"title": "Enter Quantity",
"message": "How many units?",
"inputKey": "enteredQty",
"defaultValue": "1",
"confirmLabel": "Submit",
"keyboardType": "number"
}
}

Complete contract example

This example shows a page contract with multiple action types working together:

{
"contract": {
"initialAction": "loadItems",
"scanAction": "onScan",
"actions": [
{
"id": "loadItems",
"type": "api",
"method": "GetItems",
"params": ["locationFilter"]
},
{
"id": "onScan",
"type": "api",
"method": "ProcessScan",
"params": ["scanInput"]
},
{
"id": "onFilterChanged",
"type": "filter",
"endpoint": "GetItems",
"params": ["locationFilter"]
},
{
"id": "onItemTap",
"type": "navigate",
"destination": "ITEM-DETAIL",
"data": {
"ItemNo": "{No}",
"Description": "{Description}"
}
},
{
"id": "deleteItem",
"type": "api",
"method": "DeleteItem",
"params": ["ItemNo"],
"confirm": {
"title": "Delete Item",
"message": "Remove this item from the list?",
"confirmLabel": "Delete",
"cancelLabel": "Cancel"
}
},
{
"id": "selectLocation",
"type": "lookup",
"title": "Choose Location",
"componentId": "locationRepeater"
}
],
"filters": [
{
"id": "locationFilter",
"label": "Location",
"mode": "DROPDOWN",
"optionsKey": "locations",
"labelKey": "name",
"valueField": "code"
}
]
}
}

Flow:

  1. Page loads -- the client executes loadItems, calling GetItems on the AL codeunit.
  2. User scans a barcode -- the client executes onScan, calling ProcessScan with the scanned value.
  3. User changes the location filter -- the client executes onFilterChanged, reloading items filtered by location.
  4. User taps a row -- the client executes onItemTap, navigating to ITEM-DETAIL with interpolated data.
  5. User long-presses a row and confirms deletion -- the client shows the confirm dialog, then executes deleteItem.
  6. User opens the location lookup -- the client executes selectLocation, displaying a modal populated from the locationRepeater component.