Skip to main content

JavaScript actions

JAICP DSL has special action tags, which allow a state to execute a separate script. In this embedded script, any behavior can be implemented: the bot can execute any number of reactions or make transitions between the states of this embedded script. In the main script, however, this complex business logic is represented as a single tag.

Sometimes you might need to execute an action that doesn’t switch the context to a separate script. In this case, the state can simply call a JavaScript function which implements the appropriate behavior.

In addition to script actions, JAICP DSL also supports JavaScript (JS) actions. Such action tags are implemented as regular function calls inside the script tag rather than transitions to an embedded script.

How to create a JS action

In this section, we will develop a JS action tag which:

  1. Accepts two numbers and reply format as its parameters.
  2. Makes the bot reply with the sum value in the specified format.
tip
The How to create custom action tags article shows the implementation of the same example using a script action. It is advised to read it first before continuing to this one.

JavaScript function

  1. Sign in to JAICP and select the necessary project.
  2. From the sidebar, navigate to Editor → Code.
  3. In the src directory, create a file called functions.js and write a function for your tag there.
function sumTwoNumbers(numberOne, numberTwo, answerFormat) {
var result = parseFloat(numberOne) + parseFloat(numberTwo);

if (!isNaN(result)) {
if (answerFormat === "number") {
$reactions.answer(result);
} else if (answerFormat === "full") {
$reactions.answer(numberOne + " + " + numberTwo + " = " + result);
}
} else {
$reactions.answer("I don’t know how to calculate " + numberOne + " + " + numberTwo + ".");
}
}

Let’s go over the function code:

  • The function accepts three arguments.
  • The numberOne and numberTwo parameters are converted to numbers using the parseFloat function. The numbers are added to one another, and the sum is stored in the result variable.
  • If the sum has the value of NaN, the bot reports an error; otherwise, it replies with the sum value in the specified format.
  • If answerFormat is set to "number", the bot replies with the sum only, for example: “7”. If answerFormat is set to "full", the bot replies with the full expression, for example: “3 + 4 = 7”.
caution

In JS actions, you can access the built-in variables only using the $jsapi.context method.

Tag settings

To use the above script as a action tag, you need to describe it in a special JSON settings file.

  1. In the src directory, add a subdirectory for action tags, such as blocks.
  2. In the blocks directory, add a SumTwoNumbers subdirectory containing a file called block.json.
  3. Add a JSON object with the tag settings into this file. For JS actions, some settings are different:
PropertyTypeDescription
customTagTypeStringAction tag type: SC or JS. Specify JS to make the tag a JS action.
scenarioFileStringThe path to the JavaScript file, relative to the src directory.
functionNameStringThe name of the function in scenarioFile which will be called when the tag is used. Replaces the startState property.
tip
All the other properties, including the parameter and J‑Graph apperance settings, are configured and work in the same way as their script action counterparts.

Here is a full settings example:

{
"tagName": "SumTwoNumbers",
"customTagType": "JS",
"scenarioFile": "functions.js",
"functionName": "sumTwoNumbers",
"caption": {
"eng": "Sum two numbers"
},
"description": {
"eng": "Use this block to calculate the sum of two numbers and send a reply with the result."
},
"hint": {
"eng": "Calculate the sum of two numbers and send a reply with the result"
},
"parameters": [
{
"name": "numberOne",
"type": "integer",
"required": true,
"localization": {
"eng": "First number"
}
},
{
"name": "numberTwo",
"type": "integer",
"required": true,
"localization": {
"eng": "Second number"
}

},
{
"name": "answerFormat",
"type": "string",
"required": true,
"localization": {
"eng": "Answer format"
},
"userInterfaceField": {
"type": "select",
"options": [
{
"value": "number",
"localization": {
"eng": "Number only"
}
},
{
"value": "full",
"localization": {
"eng": "Full expression"
}
}
]
}
}
]
}

The remaining steps are the same as for script actions:

Benefits of JS actions

For developers who work with the script through code, JS actions may not offer many advantages. If you import the file with the function using require and call it from the script tag, the bot behavior will remain the same:

theme: /

state: SumTwoNumbers
q!: * @duckling.number::numberOne (plus/$regex<\+>) @duckling.number::numberTwo [equals] *
SumTwoNumbers:
numberOne = {{$parseTree._numberOne}}
numberTwo = {{$parseTree._numberTwo}}
answerFormat = number
a: Should I calculate anything else for you?

However, if the script is developed through the J‑Graph visual editor, you can use the function as an action block, which is a lot more convenient.

If the function is wrapped in a JS action, it is convenient to use it in J‑Graph
You can only work with regular functions using the Code block

Differences from script action tags

Script actionJS action
Does the same as a transition to another state using go! with parameters.Does the same as a function call inside the script tag.
There can be at most one tag per state. If there are more, only the first action will be executed.There can be any number of tags per state. All the actions will be executed.
Parameter values can be extracted via the $request.data.args object.Parameter values can be extracted as standard function arguments.
It is recommended to include parameters for states of the main script where the bot should return after the action (such as okState).Since the main script continues after an action, including state parameters is not necessary.