Control Flow
Render dynamic lists and repeated content with the <for> component.
Overview
Melony provides a <for> component that lets AI render lists of items dynamically. It's perfect for displaying arrays of data like tasks, users, products, or any repeating content.
Basic Usage
The AI can use the <for> component with an items prop containing a JSON array:
<card title="Task List">
<for items='[{"task": "Buy groceries"}, {"task": "Walk dog"}, {"task": "Code review"}]'>
<text value="{{item.task}}" />
</for>
</card>This renders three text components, one for each task in the array.
Loop Variables
Inside a <for> component, you have access to these special variables:
• {{item}} - The current array item
• {{index}} - Current index (0-based)
• {{isFirst}} - Boolean, true if first item
• {{isLast}} - Boolean, true if last item
• {{isEven}} - Boolean, true if even index
• {{isOdd}} - Boolean, true if odd index
Using Loop Variables
Here's an example using multiple loop variables:
<card title="Shopping List">
<for items='[
{"item": "Apples", "qty": 5},
{"item": "Bread", "qty": 2},
{"item": "Milk", "qty": 1}
]'>
<row gap="md" align="center">
<text value="{{index + 1}}." weight="bold" />
<text value="{{item.item}}" flex="1" />
<badge label="Qty: {{item.qty}}" />
<text value="{{isLast ? 'Last item' : ''}}" size="sm" color="muted" />
</row>
</for>
</card>Nested Objects
Access nested properties using dot notation:
<for items='[
{"user": {"name": "Alice", "age": 30}},
{"user": {"name": "Bob", "age": 25}}
]'>
<card>
<text value="{{item.user.name}}" size="lg" weight="bold" />
<text value="Age: {{item.user.age}}" color="muted" />
</card>
</for>Conditional Styling
Use loop variables for conditional rendering:
<for items='[
{"status": "completed", "task": "Design"},
{"status": "pending", "task": "Development"},
{"status": "completed", "task": "Testing"}
]'>
<row gap="md">
<text value="{{index + 1}}" weight="bold" />
<text value="{{item.task}}" flex="1" />
<badge
label="{{item.status}}"
variant="{{item.status === 'completed' ? 'success' : 'warning'}}"
/>
</row>
</for>With Actions
Combine <for> with actions for interactive lists:
<card title="User List">
<for items='[
{"id": "1", "name": "Alice"},
{"id": "2", "name": "Bob"},
{"id": "3", "name": "Charlie"}
]'>
<row gap="md" align="center">
<text value="{{item.name}}" flex="1" />
<button
label="View Profile"
variant="outline"
action='{"type":"view-user","id":"{{item.id}}"}'
/>
<button
label="Delete"
variant="destructive"
action='{"type":"delete-user","id":"{{item.id}}"}'
/>
</row>
</for>
</card>Complex Example
Here's a more complex example with multiple nested components:
<for items='[
{
"project": "Website Redesign",
"tasks": 3,
"completed": 2,
"priority": "high"
},
{
"project": "Mobile App",
"tasks": 5,
"completed": 1,
"priority": "medium"
}
]'>
<card>
<row gap="sm" align="center">
<text value="{{item.project}}" size="lg" weight="bold" flex="1" />
<badge
label="{{item.priority}}"
variant="{{item.priority === 'high' ? 'danger' : 'warning'}}"
/>
</row>
<row gap="md">
<column>
<text value="Tasks" size="sm" color="muted" />
<text value="{{item.tasks}}" weight="bold" />
</column>
<column>
<text value="Completed" size="sm" color="muted" />
<text value="{{item.completed}}" weight="bold" />
</column>
<column>
<text value="Progress" size="sm" color="muted" />
<text value="{{Math.round(item.completed / item.tasks * 100)}}%" weight="bold" />
</column>
</row>
<button
label="View Details"
variant="primary"
action='{"type":"view-project","name":"{{item.project}}"}'
/>
</card>
</for>Empty States
Handle empty arrays gracefully:
<card title="Tasks">
<for items='[]'>
<text value="{{item.task}}" />
</for>
<text value="No tasks yet" color="muted" />
</card>When the array is empty, the <for> component renders nothing.
Best Practices
- Use Arrays: Always provide a valid JSON array to the
itemsprop - Template Variables: Use
{{item.propertyName}}to access item properties - Unique Keys: Include unique IDs in your items for better rendering
- Keep It Simple: Avoid deeply nested loops when possible
- Error Handling: Handle empty arrays and missing properties
Limitations
- The
itemsprop must be a valid JSON array string - Template expressions have limited JavaScript support
- Nested
<for>loops are not currently supported - Items must be objects or primitive values