Command Sequence
In its basic form the command sequence inside a Step is a simple, straight line of commands being evaluated. However, that is not all there is to it - some commands may be conditional, some may be repeated, and some commands specifically work as components of other commands.
Command hierarchy
Some commands can be set to be parents or children of other commands. This creates a relationship between the commands, usually in the way that the child commands affect the functionality of their parent somehow, but it can also be the other way around. In the documentation pages of each command there may be the sections "Parent commands" and "Child commands" - these list the other commands that the command has these special relationships with.
As an example, the command setMap creates a Map value, which is by default empty. In its documentation, setMap
has one listed child command - addMapEntry (which then has setMap
listed as a parent). An addMapEntry
command may therefore be added as a child for setMap
, making it so that the created Map starts out with the entry defined by the child command as its content instead of being empty. This relationship is marked as optional, as both setMap
and addMapEntry
can function without each other as well.
![image-20240110-144235.png](../__attachments/160563488/image-20240110-144235.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
In the Template editor, commands that are children of other commands are displayed below their parents with more indentation, like addMapEntry
in the image above. The parent commands also have a triangle displayed on the left side of them, which can be clicked to hide or show the child commands. To make a command a child of another, simply drag the child-to-be on top of its desired parent command.
While with setMap
the child relationship provides optional functionality, the relationships may alternatively be marked as required in the command documentation. As another example, the mail command sends an email message. However, it cannot do that unless it has child commands defining properties of the message - the most critical being the to command, defining the destination address of the message. Below is a typical example of mail
and its child commands forming an email message.
![image-20240110-144243.png](../__attachments/160563488/image-20240110-144243.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
Similar to how mail
cannot function at all without at least one of its potential children present, none of those children are able to function without a mail
as their parent. Required parents or children being missing will cause the commands to only produce errors informing of this during the template's evaluation.
While the commands have defined sets of possible children, it is possible to actually use any command as a child. While this doesn't serve much purpose in most cases, it can come very useful with the logic control commands, such as if and forEach. One of the design reasons why some properties of what is clearly a single operation - such as sending an email - is broken into a parent and child commands rather than being a single command with multiple attributes is basically this use of control commands to control the children. Here's the previous example modified a bit to give the email more CC addresses.
![image-20240110-144252.png](../__attachments/160563488/image-20240110-144252.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
What occurs here is that forEach
, the looping command, causes the cc
child to be evaluated for every item in the "emailCCList" Collection, therefore adding every address in that Collection into the generated email message's CC field. The if
command could be used in a similar way to make certain child commands conditional, so maybe the attachment child for example wouldn't be evaluated in some cases. This also illustrates the fact that these child-parent relationships work across commands in the hierarchy between the parent and child, they don't have to be directly linked.
However, do note that only commands that have child commands listed in their documentation have the ability to evaluate child commands. Commands that do not have any listed children do not expect to have any and so will leave any child commands given to them unevaluated.
Conditional commands
The control command if along with the command trio choose, when and otherwise exist for creating conditional sections into command sequences. Based on some condition, a set of commands does or does not get evaluated, altering how the command sequence proceeds. Here's an example of the if
command being used to control if the logic is to create a Chatter post or not.
![image-20240110-144301.png](../__attachments/160563488/image-20240110-144301.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
As you can see, the commands are made conditional through command hierarchy, with the conditional commands being children of the condition-checking control command if
. Should the variable "postToChatter" have a Boolean value of "true", the postFeedItem command and its own child will be evaluated - should "postToChatter" have some other value, the if
will not evaluate its children, causing no Chatter-posting to happen.
The commands choose
, when
and otherwise
work very similarly to if
, but allow the creation of multiple conditional sections of which only one will have its commands evaluated. This works well when you have a choice with multiple answers with different outcomes, and also if you'd like something to happen if a condition is not met, which otherwise
is for. Here's an example using these commands to select a theme based on a favorite color:
![image-20240110-144310.png](../__attachments/160563488/image-20240110-144310.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
What happens here is that if "favoriteColor" is "Orange", "theme" is set to "Sunset" and the choose
command is finished - none of the remaining options are checked since a successful result occurred. Should "favoriteColor" not be "Orange", the command moves on to check if the color is "Blue" instead and if so, sets the theme to a different kind. If it isn't that either, the otherwise
section will activate and set the theme to whatever value the "defaultTheme" variable holds. This is a typical choose
-when
-otherwise
structure, as the conditions are closely related, checking the same variable. For comparison, here's the same conditional structure using if
instead of choose
and its children:
![image-20240110-144317.png](../__attachments/160563488/image-20240110-144317.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
It doesn't look too different, aside from the if
playing the role of otherwise
- its condition has to be the reverse of the conditions preceding it. Quite a bit more complicated than just using otherwise
. This is also less efficient performance-wise, as the conditions of all three if
commands are processed regardless of whether the theme was already set, while the choose
-when
-otherwise
section will not be processing the remaining options at all if the condition of a when
resolves into "true".
Command loops
A loop is a section that repeats a set of commands for a number of times. The only source of loops within a command sequence is the control command forEach, which specifically exists for doing something with all items of a Collection. The loop is defined through child hierarchy - all the child commands of a forEach
are the ones that will be repeated as the forEach
goes through each item of the Collection one by one. Below is an example of using forEach
to define multiple attachments for a new Chatter post.
![image-20240110-144328.png](../__attachments/160563488/image-20240110-144328.png?inst-v=5205e5d1-dc16-46d7-af02-1258d99cc136)
In this example the "documentIds" variable's value can be assumed to be a Collection containing record ids of document files in Salesforce. The forEach
command will repeat the createFeedAttachment command placed as its child once for every document id in the Collection, resulting in all the documents being attached to the new post. Any command can be used within a loop, but do note that certain commands of slow performance being looped can produce notable slowdown. Certain commands may also have limits to how many times they can be evaluated, and Salesforce commands can produce Salesforce API requests which organizations have specific maximum limits for. Loops can cause the commands within to get repeated for numerous times - from tens to even thousands of times - so be aware of the potential size of your loop and the commands placed within.
Sequence interrupters
The evaluation of a command sequence within a Step or any other logic container may not always reach the end of the sequence. This can happen through specific commands that have a sequence-interrupting characteristic, as mentioned in their documentation. The commands next and return for example are such, as their evaluation causes the evaluation of the current Step or Function to end immediately. Any commands placed after them in a command sequence are therefore useless - this is why these commands are generally the last ones in the sequence, or inside conditional structures.
Another way for a sequence to get interrupted is a command error. Normally a command sequence keeps proceeding normally regardless of commands producing errors, but if the Step has an error-handling route defined, the command sequence will be interrupted if any command within the Step produces an error.