Conditions
Conditions are used to determine whether a particular branch should be taken or not. Conditions are implemented in the builder part using the ConditionBlock
class from the builder package and in the runner part using the ConditionBlock
class from the Runner library. Each Branch
can contain multiple conditions and depending on the culling
mode of the branch one, each, all, or none of the conditions should evaluate to true
in order to take the branch.
Read the condition block tutorial for step-by-step instructions on building a condition block.
🎠Condition context​
Conditions always operate for a certain context. There are five types of context available (the context type of a condition is defined in the @tripetto
decorator used to register a condition to the builder):
*
: The block context is the whole form (for example, the Device condition that evaluates the type of device used for the form);section
: The block context is a certain section;branch
: The block context is a certain branch;node
: The block context is a certain node;typeof NodeBlock
or string: The block context is a certainNodeBlock
type (for example, a condition that verifies if a certain option of the dropdown block is selected). In order to bind the right context to the condition, it is possible to define condition templates for blocks. That enables blocks to serve a list of possible conditions for a block to the builder. See the condition templates section for more information.
✅ Condition evaluation​
The condition evaluation code itself is defined by declaring a condition method within the condition block class of the runner part. This method then needs to be decorated with the @condition
decorator. This decorator instructs the runner to execute the condition method whenever it wants to evaluate the condition. There are two modes of operation for the condition evaluation:
Synchronous evaluation​
A synchronous condition is very simple: It should return true
if the condition satisfies or false
if it does not:
import { tripetto, condition, ConditionBlock, Callback } from "@tripetto/runner";
@tripetto({
type: "node",
identifier: "example-condition",
})
class ExampleConditionBlock extends ConditionBlock {
@condition
evaluate(): boolean {
return true;
}
}
Asynchronous evaluation​
Asynchronous evaluation allows a condition to perform an asynchronous process to evaluate a condition. For example, a block that uses an external API to evaluate a condition.
To indicate asynchronous evaluation, the condition method should implement the callback
argument and return it as return value.
import { tripetto, condition, ConditionBlock, Callback } from "@tripetto/runner";
@tripetto({
type: "node",
identifier: "example-condition",
})
class ExampleConditionBlock extends ConditionBlock {
@condition
evaluate({ callback }: { callback: Callback<boolean> }): Callback<boolean> {
// Call an endpoint
fetch("/example-server")
.then((response) => {
if (response.ok) {
// All ok, condition passed!
callback.return(true);
} else {
// Not so good, condition failed!
callback.return(false);
}
});
// Indicate asynchronous evaluation
return callback;
}
}
Whenever asynchronous evaluation is active, the isEvaluating
field of the runner may be set to true
in some cases. Runners can use this to indicate the form respondent that the form is "busy" (for example, by showing a loading spinner in the UI).
📒 Condition templates​
The builder part of a block can supply a list of possible conditions for the block to the builder. To do so, we need to add a method to the NodeBlock
class and then decorate it with the @conditions
decorator. This method will then be invoked by the builder when it wants to know if there are any conditions available for the block. We can use the conditions
field of the NodeBlock
class to define condition templates. Here's an example:
import { tripetto, conditions, NodeBlock } from "@tripetto/builder";
@tripetto({
type: "condition",
context: ExampleBlock,
identifier: "example-condition",
label: "Example condition",
icon
})
export class ExampleCondition extends ConditionBlock {
value: boolean;
}
@tripetto({
type: "node",
identifier: "example",
label: "Example block",
icon
})
export class ExampleBlock extends NodeBlock {
@conditions
onConditions(): void {
this.conditions.template({
condition: ExampleCondition,
label: "Example condition is true",
props: {
value: true
}
});
this.conditions.template({
condition: ExampleCondition,
label: "Example condition is false",
props: {
value: false
}
});
}
}
This code adds two condition templates for a condition named ExampleCondition
. The props
property allows to set the initial value of fields of the condition (in this case, it sets a value to the value
field of ExampleCondition
class). The context for the condition is the ExampleBlock
instance. This allows the builder user to add the condition through the context menu of the node block, like the menu that is shown in the following example:
Condition template methods​
You can use the following methods for defining condition templates: