Jinja uses brace delimiters to distinguish between expressions and statements. Specifically, it uses double curly braces {{ }} to surround expressions that should be replaced with output, and curly braces with percent signs {% %} to surround statements that control the logic of the template. Jinja uses the {# #} syntax for comments. Anything between the opening and closing comment delimiters will be ignored by Jinja and not included in the output.
- Output values (
{{ }}): Display variables or expressions. For example,{{ CTX.user_id }}shows user-specific data. - Code blocks (
{% %}): Used for control structures likeif,else,forloops. - Comments (
{# #}): Enable non-executable notes for clarity.
The Monaco Editor is a powerful code editor that allows you to edit and preview Jinja templates in real-time. Access the Monaco Editor in many places in the product, whenever you see the clickable
next to a field or menu section.
Here are some features and keystrokes you can use with the Monaco Editor in Rewst:
- Syntax highlighting: The Monaco Editor provides syntax highlighting for Jinja templates, making it easier to read and understand your code.
- Code completion: The Monaco Editor provides code completion for Jinja templates, suggesting possible completion options as you type.
- Find and Replace: The Monaco Editor provides a powerful Find and Replace feature that allows you to quickly search for and replace text within your code.
- Keyboard shortcuts: The Monaco Editor provides a variety of keyboard shortcuts that can help you to work more efficiently. For example:
- Ctrl + Space: Trigger code completion
- Ctrl + /: Toggle line commenting
{% hint style="info" %} Note that Rewst's Jinja2 implementation displays mutable object— lists, dicts, namespaces— in their final state immediately when first rendered, rather than their current state at render time. This differs from standard Jinja2 behavior where objects should display their state at the time of rendering. {% endhint %}
{% hint style="info" %} JSON, or JavaScript Object Notation, is a lightweight format for storing and transporting data, often used when data is sent from a server to a web page. When using JSON:
- Data is organized in key-value pairs, also called context variables in Rewst workflows. For example, "action" is a key and "add" could be the value.
- Data is separated by commas.
- Curly braces hold objects. Correct formatting includes both opening and closing curly braces.
- Square brackets hold arrays. {% endhint %}
Example:
{
"name": "Han Solo",
"age": 34,
"favorites": ["spaceships", "adventures"]
}Generally, variables are labeled containers for data that you want to use in your workflow. Variables store task results, facilitate dynamic content generation, and enhance the readability and maintainability of Jinja templates. For example, instead of updating every user's individual name in multiple places, use a variable of CustomerName to hold whatever name is needed instead, seamlessly updating as needed in every place the variable is used.
The Context is a central storage space that keeps track of all data generated, captured, or used throughout a workflow. Think of it as a shared memory for a specific workflow, containing all that workflow's information. Every time a Rewst workflow runs, the data processed is shown in JSON format in the context of the workflow.
Key objects like action, user_id, and group_id are visible as part of the context data. These were configured in the workflow input and are now accessible for use in Jinja code.
Click on the blue icon to the right of fields to access The Context
as it pertains to that field.
Type CTX. in between the curly braces to expose all
available options.
Variables in Rewst are specifically referred to as data aliases. Data aliases defined within a workflow are prefixed with CTX for context variable, and stored in The Context. There are several variable types in Jinja. Learn more about them here.
- Use context (CTX) variables in data aliases on your task's transitions to capture specific elements from the JSON data produced by your workflow's tasks. This is pivotal for storing and manipulating workflow data.
- These types of variables can be created and modified by workflow tasks but are not global. Their scope is confined to the workflow.
{% hint style="info" %} Variables do not automatically inherit down into subworkflows or up from subworkflows. In order to pass these values through, they need to be defined as input or output variables {% endhint %}
Jinja supports conditional statements like if, else and elif. These statements allow you to create dynamic workflows based on specific conditions, ensuring the workflow adapts to varying scenarios.
Examples:
The if statement allows you to control the flow of your template based on certain conditions. If the first condition is true, expression 1 will be executed. If the first condition is false and the second condition is true, expression 2 will be executed. If both conditions are false, expression 3 will be executed.
{% if condition %}
expression 1
{% elif condition2 %}
expression 2
{% else %}
expression 3
{% endif %}{% if rooster_sound == 'cock-a-doodle-doo' %}
<p>Time to rise and shine!</p>
{% elif rooster_sound == 'moo' %}
<p>The rooster is having an identity crisis. Someone check the barnyard!</p>
{% else %}
<p>The rooster is trying out new sounds. Perhaps it's starting a band!</p>
{% endif %}{% if user_is_looged_in %}
<p>Welcome, {{ user_name }}!</p>
{% else %}
<p>Please log in to continue.</p>
{% endif %}For loops in Jinja enable you to iterate through JSON lists, executing actions for each item. The pointer, such as thing, points to items within the list, facilitating dynamic data processing.
Examples:
In this example, the for loop iterates over a list called items and prints each item to the output. The item variable represents the current item in the list being iterated over. The tag marks the end of the loop.
{%- set items = ["crawfish", "butter", "rice", "garlic", "onions"] -%}
{% for item in items %}
{{ item }}
{% endfor %}{% for thing in CTX.list_of_things %}
<li>{{ thing }}</li>
{% endfor %}In this snippet, the loop iterates through numbers from 0 to 8, appending each value to the mylist variable, which is then displayed.
{% set mylist = [] %}
{%- for item in range(0,9) -%}
{% do mylist.append(item) %}
{% endfor %}
{{ mylist }}For more detailed information on Jinja filters, see our list here.
Jinja filters are functions that can be applied to variables and expressions within Jinja templates to modify their output. They are used to perform a wide range of data manipulations, such as formatting strings, converting data types, and filtering lists. Some commonly used filters include upper, lower, title, default, join, and random. Jinja also allows for the creation of custom filters to meet specific needs. Overall, filters are a powerful tool that can help you to manipulate data more easily and efficiently within your Jinja templates
Examples:
- Truncate text:
{{ text|truncate(20) }} - Capitalize names:
{{ user_name|capitalize }} - Lowercase and replace text:
{{ user_email|lower|replace("@", "at") }}
Variable expressions are encapsulated by double curly braces ({{ and }}) and will output the value of the variable or expression as they are evaluated.
{{ CTX.my_var }}
These are used for decision-making functions such as sets, if statements and for eaches. They are encapsulated by curly+percent signs ({% %})
{% set x = 100 %}These statements typically do not output anything.
Functionally, comments do nothing. In the Rewst Monaco editor, you can use the hotkey CTRL-/ to comment blocks of code.
{# COMMENT #}
By default, when Jinja begins a statement block, it preserves any whitespace characters such as spaces, carriage returns, etc., before or after the block. In many cases, you'll want to remove any spaces you did not explicitly intend to have, so the addition of the - character in the open and closing braces will remove the whitespace before or after the statement, respectively.
{%- for part in parts_list -%}
{{- part.name -}}
{%- endfor -%}List comprehension efficiently creates new lists from existing ones, based on specific criteria. It tailors data selection in workflows, enhancing efficiency and precision. Create a new list from an existing one in a simplified way, without needing to end the code with {% endfor %}.
You can combine filters and conditions to produce concise, targeted lists, all in one Jinja expression.
“Give me a list of all X from Y, but only if Z.”
It consists of three parts:
- Output: Define what you want to extract or manipulate - e.g.,
user.id. - For Loop: Specify the list to iterate over - e.g.,
CTX.my_user_list. - Conditions - optional: Apply conditions to filter data - e.g.,
if user.enabled == true.
Here is the basic structure of list comprehension.
{{
[ output for output
in CTX.list
if condition ]}}
Example: Filter active users from CTX.my_user_list.
{{
[
user.id
for user in CTX.my_user_list
if user.enabled == true
]
}}This flavor of list comprehension allows you to filter data based on specific criteria, ensuring more accurate and relevant data processing, critical for complex workflows. For example, using filters like lower to standardize data before comparison.
This method allows you to apply specific mathematical functions to each element in a list, thereby modifying the output based on your needs. It offers a succinct method to apply mathematical transformations across a list, yielding a new list with modified values.
Example:
squared_numbers = [num * num for num in list_of_numbers]If list_of_numbers = [1, 2, 3, 4], then the squared_numbers list after applying the above list comprehension will be [1, 4, 9, 16].
This concise approach efficiently applies the squaring function to each item in the original list and collects the results in a new list.
With Items is the equivalent to a foreach statement in other languages. With this, you can pass a list of parameters into a certain action, based on the parameters of a specific task or subworkflow, collect the results from each, and then do something with that information. Learn more about how to achieve this in our workflows documentation.
With Items is sometimes but not always used in conjunction with collected results. Collected results only applies if the task or subworkflow is outputting something that you want in the result. Otherwise, you don't have to use it. Consider these two examples:
Delete every single user that's inactive.
Since that action wouldn't give us anything back, you don't need to use collected results.
Get a list of inactive users for each client that we manage.
This would return a long list, and does require you to use collected results.
Each time a task or subworkflow runs using With Items, a new result section is created. Each new result section is stored in the task or subworkflow's collected results. Collected results is the list of all the results of a single With Items execution. To use multiple collected results in a single parent workflow, you would need to repeat the process for each subworkflow separately.
Choose which of the following two methods you would like to use for collected results. Both will net the same goal, and which you use is generally a matter of preference:
- Add a noop action to your Workflow Builder canvas; it's best practice to start with a noop to make it clear where your collected results will start. Name it something descriptive, following the format
<taskname>_collected_results. - Add a transition between the noop task and your task or subworkflow so that it runs after the execution.
- Create a data alias in the transition. Name it something descriptive that relates to the name you gave the noop, following the format
get_<taskname>_collected_results. - Click
to open the Jinja editor. - Enter the following syntax to work with list comprehension and add a list of the group result inside of the modification_results variable:
{{
[
collected_result.result.<variable_name>
for collected_result in TASKS.<nameoftaskorsubworkflow>.collected_results
]
}}
- Use the following syntax to call the collected results, which will appear in the context if you have properly set up your data alias.
{{ TASKS.<task_name>.collected_results }} - Add a noop action to your Workflow Builder canvas; it's best practice to start with a noop to make it clear where your collected results will start. Name it something descriptive, following the format
get_<taskname>_collected_results. - Add a transition between the noop task and your subworkflow so that it runs after the subworkflow.
- Enter
pra_collected_resultsin the publish result as field of the parameters for that noop. This will put the entire collected results into a single variable.
{% hint style="info" %} Interested in seeing Jinja examples in the platform? Search the crate marketplace for Rewst Examples: Jinja Comprehension. Once it's unpacked you'll find common Jinja examples provided by our ROC. {% endhint %}



