APL User-defined Commands


You can define custom commands in your APL document or package.

Overview of user-defined Commands

The commands property in the APL document to define a set of commands. A user-defined command can call APL standard commands.

For example, this creates a command called slideInFromRight that calls the AnimateItem command:

{
  "commands": {
    "slideInFromRight": {
      "parameters": [
        "distance"
      ],
      "command": {
        "type": "AnimateItem",
        "easing": "ease-in-out",
        "duration": 300,
        "values": [
          {
            "property": "opacity",
            "from": 0,
            "to": 1
          },
          {
            "property": "transformX",
            "from": "${distance}",
            "to": 0
          }
        ]
      }
    }
  }
}

To use a parameterized command, pass the name of the command as the type:

{
  "type": "TouchWrapper"
  "onPress": {
    "type": "slideInFromRight",
    "duration": 500,
    "distance": "20vw"
  }
}

In the above example the distance parameter will be bound to 20vw in the translateX property animation. The duration of the command will be 500 milliseconds (the value 500 passed in as the duration overrides the internal 300 millisecond duration).

Command definitions

The command property in the document is a map of command name to a command definition. The command definition contains the following properties:

Property Type Required Description
parameters Array of parameter definitions No Optional named parameters to add to the data-binding context
command, commands Array of commands Yes The array of commands to run
description String No Description of this command

commands

The command property is an implicit sequential block of commands to run. The array of commands supports the standard data-binding with array rules including automatic conversion of a single command into an array of commands and substitution of parameters into the array.

parameters

The parameters are named values that can be passed as arguments. Each parameter is an object with the following properties:

Property Type Required Description
default Any No The default value to apply if this parameter is not specified. Defaults to empty.
description String No A user-provided description of this parameter
name String Yes The parameter name
type any, array, boolean, color, dimension, integer, map, number, object, string No The type of the parameter. Defaults to any

The parameter name must be a unique name starting with an upper- or lower-case letter and containing no white space ([a-zA-Z][a-zA-Z0-9]*).

As a convenience, a simple parameter name can be used instead of the parameter object (for example, "title" instead of { "name": "title", ... }. This is not recommended, but does allow compact command definition for cases where no type coercion or defaults values are required.

Command inflation

Commands are inflated with the following algorithm:

  • Each parameter is evaluated and added to the data-binding context.
  • The command array is evaluated.
  • Properties assigned to the object but not matching a named parameter are passed to each command as properties.

For example, note this definition of customPressHandler:

    "commands": {
      "customPressHandler": {
        "description": "Hide the current component and fire an event if checked."
        "parameters": [
          "onChecked",
          {
            "type": "number",
            "name": "opacity",
            "default": 0.5
          }
        ],
        "commands": [
          {
            "type": "SetValue",
            "property": "opacity",
            "value": "${opacity}"
          },
          {
            "type": "Sequential",
            "when": "${event.target.checked}",
            "commands": [
              "${onChecked}"
            ]
          }
        ]
      }
    }

Now assume this custom command is invoked with:

{
  "onPress": {
    "type": "customPressHandler",
    "onChecked": {
      "type": "SendEvent",
      "arguments": ["It was checked!"]
    },
    "delay": 500
  }
}

When the onPress handler fires, the inflated command representation is:

[
  {
    "type": "SetValue",
    "property": "opacity",
    "value": 0.5,
    "delay": 500
  },
  {
    "type": "Sequential",
    "when": "${event.target.checked}",
    "delay": 500,
    "commands": [
      {
        "type": "SendEvent",
        "arguments": ["It was checked!"]
      }
    ]
  }
]

Note the following:

  • The original invocation passed a delay value of 500. The customPressHandler definition does not include delay as a parameter, so the delay value was passed into each of the commands in the custom command.
  • The original invocation did not pass an opacity value, but opacity is defined as a parameter in customPressHandler. So the data-binding context was extended by the default value of opacity - in this case 0.5. That value was used in the SetValue command expansion of ${opacity}.

Nested Expansion of User Commands

You can define user commands that reference other user commands. For example:

{
  "SoftStagger": {
    "description": "General soft-stagger sliding objects from the left or right",
    "parameters": [
      "delay",
      "duration",
      "distance"
    ],
    "commands": [
      {
        "type": "SetValue",
        "property": "opacity",
        "value": 0
      },
      {
        "type": "AnimateItem",
        "values": [
          {
            "property": "opacity",
            "to": 1
          },
          {
            "property": "translateX",
            "from": "${distance}",
            "to": 0
          }
        ],
        "delay": "${delay}",
        "duration": "${duration}",
        "easing": "ease-out"
      }
    ]
  }
}

You can use the SoftStagger command as is and pass in the parameters for delay, duration, and distance. You can also use SoftStagger to define some standard variations for convenience:

{
  "SoftStagger1": {
    "commands": {
      "type": "SoftStagger",
      "delay": 0,
      "duration": 666,
      "distance": 40
    }
  },
  "SoftStagger2": {
    "commands": {
      "type": "SoftStagger",
      "delay": 50,
      "duration": 666,
      "distance": 40
    }
  }
}

You can then add a soft stagger entrance animation to a component with a line like this: onMount:{"type": "SoftStagger2"}.


Was this page helpful?

Last updated: Nov 28, 2023