Documentation
@for
Iterate over arrays and collections to render lists.
Basic Usage
var items = ["Apple", "Banana", "Cherry"]
<Column class="gap-8">
@for (item in items) {
<Text>{item}</Text>
}
</Column> With Objects
data class User(val id: String, val name: String)
var users = [
User("1", "Alice"),
User("2", "Bob"),
User("3", "Charlie")
]
@for (user in users) {
<Card class="p-16">
<Text>{user.name}</Text>
</Card>
} With LazyColumn
<LazyColumn class="gap-12">
@for (show in shows) {
<ShowCard show={show} />
}
</LazyColumn> Whitehall automatically transforms @for in lazy lists to items().
Empty State
@for (item in items) {
<Text>{item.name}</Text>
} empty {
<Text color="#999">No items found</Text>
} With Index
@for (item in items.withIndex()) {
<Row class="gap-8">
<Text>#{item.index + 1}</Text>
<Text>{item.value.name}</Text>
</Row>
} Complex Expressions
Whitehall supports complex loop expressions:
// Take first 4 items
@for (genre in genres.take(4)) {
<Chip text={genre} />
}
// Range with condition
@for (i in 0 until minOf(4, items.size)) {
<Text>{items[i]}</Text>
}
// With step
@for (i in 0 until items.size step 2) {
<Text>{items[i]}</Text>
} Filtered Lists
var searchQuery = ""
var items = [...]
val filtered = items.filter {
it.name.contains(searchQuery, ignoreCase = true)
}
@for (item in filtered) {
<ItemCard item={item} />
} empty {
<Text>No results for "{searchQuery}"</Text>
} With Keys (Animations)
Add key for list animations:
<LazyColumn>
@for (item in items) {
<Row key={item.id} animate:flip={{ duration: 200 }}>
<Text>{item.name}</Text>
</Row>
}
</LazyColumn> LazyVerticalGrid
<LazyVerticalGrid columns={2} gap={16}>
@for (product in products) {
<ProductCard product={product} />
}
</LazyVerticalGrid> FlowRow (Wrapping)
<FlowRow gap={8}>
@for (tag in tags) {
<Chip text={tag} />
}
</FlowRow> Nested Loops
data class Category(val name: String, val items: List<String>)
var categories = [...]
@for (category in categories) {
<Column class="gap-8">
<Text fontSize={20} fontWeight="bold">{category.name}</Text>
@for (item in category.items) {
<Text>{item}</Text>
}
</Column>
} With Click Handlers
@for (show in shows) {
<Card onClick={() => $navigate("/show/${show.id}")}>
<Image src={show.poster} />
<Text>{show.name}</Text>
</Card>
} Grouped Data
val grouped = items.groupBy { it.category }
@for ((category, items) in grouped) {
<Column class="gap-8">
<Text fontSize={18}>{category}</Text>
@for (item in items) {
<Text>{item.name}</Text>
}
</Column>
} Ranges
// Simple range
@for (i in 1..10) {
<Text>Item {i}</Text>
}
// Range to list
val numbers = 1..10
@for (n in numbers) {
<Text>{n}</Text>
}
// With step
@for (i in 0..100 step 10) {
<Text>{i}%</Text>
} Behind the Scenes
Whitehall transpiles @for based on context:
Regular Composables
@for (item in items) {
<Text>{item}</Text>
}
// Becomes:
items.forEach { item ->
Text(text = item)
} LazyColumn/LazyRow
<LazyColumn>
@for (item in items) {
<Text>{item}</Text>
}
</LazyColumn>
// Becomes:
LazyColumn {
items(items) { item ->
Text(text = item)
}
} Use LazyColumn/LazyRow for large lists. They only compose visible items, providing better performance and memory usage.
Complete Example
data class Show(
val id: String,
val name: String,
val poster: String,
val rating: Double
)
var shows: List<Show> = []
var isLoading = true
$onMount {
launch {
shows = $fetch("https://api.example.com/shows")
isLoading = false
}
}
<Column p={16}>
@if (isLoading) {
<CircularProgressIndicator />
} else {
<LazyColumn class="gap-16">
@for (show in shows) {
<Card
key={show.id}
onClick={() => $navigate("/show/${show.id}")}
animate:flip={{ duration: 200 }}
>
<Row class="gap-12">
<Image
src={show.poster}
w={80}
h={120}
fit="cover"
class="rounded"
/>
<Column class="gap-4">
<Text fontSize={18} fontWeight="bold">{show.name}</Text>
<Row class="gap-4">
<Icon name="star" size={16} color="#f59e0b" />
<Text>{show.rating}/10</Text>
</Row>
</Column>
</Row>
</Card>
} empty {
<Column align="center" p={40}>
<Text fontSize={18} color="#999">No shows found</Text>
</Column>
}
</LazyColumn>
}
</Column> See Also
- @if / @else - Conditional rendering
- animate:flip - List animations
- Lists - LazyColumn/LazyRow components