Skip to content

Action Binding and Result

Action Binding

Using Action Binding to Share Data Between Actions and Pages

Action binding allows you to set the action's binding context for use during an action execution chain. Action binding can be accessed in all actions and rules in the chain.

To set an action binding, when a rule is triggered by an event, the app must set action binding to the PageProxy of the current page. Once you have set the action binding in the rule, it will become the binding context of all subsequent chained actions and rules you execute.

If you navigated to a page at the end of the chain, the target page's binding will be set with the content from the action binding. Allowing you to display binding in the page.

Note

There is only one copy of action binding for each instance of a page and it is stored in the PageProxy object. All actions and rules in the execution chain will be accessing the content from the same action binding object.

The following example will execute a chain of action and rules and will demonstrate how to create, access and modify action binding:

OnButtonPressed.js -> ShowNewPropertyValue.action -> ModifyNewProperty.js -> ShowUpdatedNewPropertyValue.action.

An OnPress event triggered the following rule:

export default OnButtonPressed(context) {
  let pageProxy = context.getPageProxy();
  pageProxy.setActionBinding({
    "NewProperty": "1001"
  });

  return context.executeAction("/MyApp/Actions/ShowNewPropertyValue.action");
}

This action will show a message dialog with the text "NewProperty's value is 1001":

// /MyApp/Actions/ShowNewPropertyValue.action
{
  "_Type": "Action.Type.Message",
  "Message": "NewProperty's value is {NewProperty}",
  "OKCaption": "OK",
  "OnSuccess": "/MyApp/Actions/ShowNewPropertyValueInRule.js"
}

You can modify the content of the action binding in another rule down the chain:

export default ModifyNewProperty(context) {
  let pageProxy = context.getPageProxy();
  let actionBinding = pageProxy.getActionBinding();
  if (actionBinding) {
    actionBinding.NewProperty = "9009";
    return context.executeAction("/MyApp/Actions/ShowNewPropertyValue.action");
  }
  else {
    // This should never be reached. The binding should be there if the actions and rules are chained correctly
    alert("The action binding is not set. It should have been set in the OnButtonPressed rule. Did you chain the execution correctly?");
  }
}

This action will show a message dialog with the text "Updated NewProperty's value is 9009":

// /MyApp/Actions/ShowUpdatedNewPropertyValue.action
{
  "_Type": "Action.Type.Message",
  "Message": "Updated NewProperty's value is {NewProperty}",
  "OKCaption": "OK",
  "OnSuccess": "/MyApp/Actions/NavigateToPageB.action"
}

When the app navigated to PageB.page, it will take the content of the action binding and set it as the page's binding. And in turns, the UI controls defined in this page can bind to the page's binding.

When the following page is displayed, it will display an Object Cell with title text: "NewProperty in page's binding is 9009"

{
  "_Type": "Page",
  "_Name": "PageB",
  "Controls": [{
    "Sections": [{
      "_Type": "Section.Type.ObjectTable",
      "ObjectCells": [{
        "ObjectCell": {
          "Title":"NewProperty in page's binding is {NewProperty}",
        }
      }]
    }]
  }]
}

Auto Set Action Binding

There are certain cases where action binding will be automatically set when an event is triggered.

If the UI control that triggers the event has binding, the binding will be automatically set as the action binding in the execution chain. Otherwise, if the page has binding, the page binding will be automatically set as the action binding in the execution chain.

For example:

When you are on a page and you have bound an Object Table control to a Products entity set that returns 100 records. Each of the object cell in the table will be bound a product entity, so when user pressed e.g. 10th item of the cells, its OnPress event will be triggered with the action binding contains data of the 10th Products entity. This is useful so that if you navigate the detail page, its binding already is the selected product.

When you are on the detail page with binding of a product and user pressed a button (e.g. 'Edit' button) in the action bar, its OnPress event will be triggered with the action binding contains the same data from the page's binding. That is because the action bar does not its own binding, so the page's binding will used instead.

Action Results

Some actions can return result. An action's result can be success with data or failure with error. This result can be accessed via ActionResult.

In order to access result of the action you must first assign a name to the ActionResult. When defining an action, you can assign a value to the ActionResult._Name property. That value will be name you can use to access the result of that specific action after it was executed.

The result will be stored in an object of type IActionResult.

If the action execution succeeded, the content of the result is stored in the IActionResult.data property. If the action execution failed, the error is stored in the IActionResult.error property.

For example, the following ODataService CreateEntity action is defined with action result named "createCustomerResult"

{
  "_Type": "Action.Type.ODataService.CreateEntity",
  "Target": {
    "Service": "/MyMDKApp/Services/MyOData.service",
    "EntitySet": "Customers"
  },
  "Properties": {
    "CompanyName": "#Control:CompanyName/#Value",
    "ContactName": "#Control:ContactName/#Value"
  },
  "OnSuccess": "/MyMDKApp/Rules/CreateEntitySuccess.js",
  "OnFailure": "/MyMDKApp/Actions/CreateEntityFailureMessage.action",
  "ActionResult": {
    "_Name": "createCustomerResult"
  }
}

When the above action is executed and is successful, CreateEntitySuccess.js rule will be executed and you will be able to access its result via the getActionResult API.

export default function CreateEntitySuccess(context) {
  let actionResult =  context.getActionResult("createCustomerResult");
  if (actionResult && actionResult.data) {
    //the result of the action is always contained in the 'data' property
    alert(`Customer ${actionResult.data.ContactName} is created successfully`);
  }
  else {
    alert("Can't find action result");
  }
}

When the above action is executed and failed, CreateEntityFailureMessage.action will be executed and you will be able to access its result via the #ActionResult:<ActionResultName> Target Path.

{
  "_Type": "Action.Type.Message",
  "Message": "{#ActionResult:createCustomerResult/error}",
  "OKCaption": "OK"
}

Last update: August 12, 2020