For Each Loops
Iterate over collections in workflows.
The For Each step lets you iterate over collections, running workflow steps for each item. This is essential for processing repeatable groups, data table rows, or any array data.
When to Use For Each
Common use cases:
- Process each item in an order
- Validate each row in a repeater
- Update multiple related entries
- Aggregate calculations across items
Creating a For Each Loop
Basic Setup
- Add a For Each step
- Configure the collection to iterate
- Add steps inside the loop
- Connect the loop exit
Visual Structure
For Each (items)
↓
[Loop Body]
Step A → Step B
↓
[Loop Exit] → Next Step
Collection Types
Repeater Field Instances
Iterate over repeating group entries:
Collection: entry:current.answers.order_items
Each iteration has access to:
- Instance ID
- All field values in that instance
Data Table Rows
Iterate over data table results:
Collection: data_table:products[category="active"]
Each iteration provides:
- Row ID
- All column values
Array Values
Iterate over multiselect or array fields:
Collection: entry:current.answers.selected_categories
Each iteration provides:
- Array index
- Current value
Calculation Results
Iterate over computed arrays:
Collection: workflow:get_items.outputs.result
Accessing Loop Data
Current Item
Inside the loop, access the current item:
{{ loop.current }}
{{ loop.current.name }}
{{ loop.current.quantity }}
Loop Metadata
| Variable | Description |
|---|---|
loop.index | Current index (0-based) |
loop.index_path | Full path for nested loops |
loop.item_id | Unique ID for current item |
loop.current | The current item data |
For Repeater Items
When iterating repeater instances:
loop.item_id = instance ID (e.g., "abc123")
loop.current = { field_values }
Loop Body Steps
Running Steps
Steps inside the loop run for each item:
For Each: items
↓
Calculate: item_total = loop.current.price * loop.current.qty
↓
Update: items[{{ loop.item_id }}].total = item_total
Accessing Previous Steps
Within the loop, reference other loop step outputs:
{{ workflow:calc_item.outputs.result }}
This gets the result from the same iteration.
Nested Loops
Loops can be nested for multi-level data:
For Each: orders
↓
For Each: loop.current.items
↓
Process item
Nested Index Paths
For nested loops:
loop.index_path = "0.2.1" // 1st order, 3rd item, 2nd sub-item
Accessing Parent Loop
In nested loops, access parent data:
{{ loop.parent.current.order_id }}
Aggregating Results
Collect Results
Each loop iteration can produce outputs:
For Each: items
↓
Calculate: item_total
↓
[Loop outputs collected]
Access All Results
After the loop:
workflow:foreach.outputs.iter_outputs
workflow:foreach.outputs.iter_outputs[0].item_total
Aggregate in Next Step
Calculate totals after loop:
SUM(workflow:foreach.outputs.iter_outputs|pluck:"item_total")
Example: Order Processing
Scenario
Process each item in an order:
- Calculate line total
- Update item record
- Sum order total
Workflow
Trigger: Form Submitted
↓
For Each: order_items
↓
Calculate: line_total = price * quantity
↓
Update: items[{{ loop.item_id }}].line_total = line_total
↓
Calculate: order_total = SUM(items|pluck:"line_total")
↓
Update: total = order_total
Example: Validation
Scenario
Validate each employee record in a repeater.
Workflow
For Each: employees
↓
Condition: loop.current.email is_empty
├─ True: Set: items[{{ loop.item_id }}].valid = false
└─ False: Set: items[{{ loop.item_id }}].valid = true
↓
Condition: ANY items|pluck:"valid" = false
└─ True: Update entry.status = "needs_review"
Best Practices
Limit Iterations
For very large collections:
- Consider pagination
- Process in batches
- Use server-side processing for 100+ items
Error Handling
Handle errors within loops:
For Each: items
↓
API Call
├─ Success: Continue
└─ Error: Log error, continue to next item
Performance
- Minimize API calls inside loops
- Batch operations when possible
- Use calculations for aggregations
Testing
- Test with empty collections
- Test with single item
- Test with many items
- Check edge cases