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 | Current loop index path |
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.
Loop Limits
For Each steps cannot be placed inside another For Each loop. If you need to process multi-level data, split the work into separate workflows or flatten the collection before the loop runs.
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
- Keep loops single-level; nested For Each steps are not supported
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
- Keep loop body steps focused on the smallest useful unit of work
- Use calculations for aggregations
Testing
- Test with empty collections
- Test with single item
- Test with many items
- Check edge cases