Custom Actions provide an easy way to define reusable client side functionality your team can reuse across your application. Just like the built-in actions provided as part of Visual Builder, custom actions can be incorporated into action chains and help you define business logic flows in a declarative way.

A custom action is defined using a JSON file that define the meta-data for the action, and a JavaScript file that holds the logic the action implements. You can define parameters that will be passed into the action, and the results and output that the action will return.

In the video demo we define a reusable function that performs a client-side search for a value in a field in an array. We can then use this function in multiple places in our app.

Custom actions are created in the resources section of your application and are defined in a directory structure – so the minimum name for an action would be directory/actionname.

The action will be created with two files a js file for the actual code of the logic, and a json file that has the metadata for the action.

To the json file you can add parameters that your action will receive (One parameter sample is already in place), for example:

  "propertyInspector": [
    {
      "name": "title",
      "label": "Ticket Title",
      "type": "string",
      "component": "inputText",
      "required": true
    },
        {
      "name": "ticketprice",
      "label": "Price per Ticket",
      "type": "number",
      "component": "inputText",
      "required": false
    } 
  ]
}

You'll also need to define the result of the action using code like this:

 "resultShape": {
    "result": "string"
  },

In your code you can simply refer to the parameters by their names. And to return an outcome and a value from the action chain use code such as:

      return Action.createSuccessOutcome({ "result": "done" });

To use your action chain in the application, you'll need to add a reference to it in your application's json definition.

Add a require JS reference like this:

    "requirejs": {
   "paths": { 
      "team/printPDF" : "resources/actions/team/printpdf/action"
    } 
}

Here are the files used in the video sample:

action.json

{
  "id": "team/findInArray",
  "category": "Team",
  "displayName": "findInArray",
  "iconClass": "oj-ux-ico-action",
  "resultShape": { "result": "array" },
  "propertyInspector": [
    {
      "name": "array",
      "label": "Array to filter",
      "type": "string",
      "component": "inputText",
      "required": true
    },
        {
      "name": "fieldname",
      "label": "Field to search",
      "type": "string",
      "component": "inputText",
      "required": true
    },
        {
      "name": "filter",
      "label": "Value to find",
      "type": "string",
      "component": "inputText",
      "required": true
    }
  ]
}

action.js

define(['vb/action/action'], (Action) => {
  'use strict';

  class CustomAction extends Action {
    perform(parameters) {
      var retArray = parameters.array.find(record => record[parameters.fieldname] === parameters.filter);
      if (retArray) {
        return Action.createSuccessOutcome({ "result": retArray });

      } else {
        return Action.createSuccessOutcome({ "result": [] });

      }
    }
  }

  return CustomAction;
});

For more on custom actions – check our documentation on action chains.