List Rendering
Learn how to work with collections of data like arrays and maps. The repeat.for functionality allows you to loop over collections of data and work with their contents similar to a Javascript for loop.
The repeat.for
binding iterates over collections to render lists of data. It works with arrays, sets, maps, and ranges, creating a template instance for each item.
The repeat.for
Binding
repeat.for
BindingAt its core, repeat.for
acts like a template-based for...of
loop. It iterates over a collection and creates a new rendering context for each item. For example:
<ul>
<li repeat.for="item of items">
${item.name}
</li>
</ul>
This snippet tells Aurelia to:
Loop over each element in the
items
collection.Assign the current element to a local variable named
item
.Render the element (here, displaying
item.name
) for each iteration.
JavaScript Analogy:
for (let item of items) {
console.log(item.name);
}
Keyed Iteration for Efficient DOM Updates
When working with dynamic collections, you can specify a unique key for each item to optimize DOM updates. Aurelia uses keys to:
Track which items have been added, removed, or reordered
Only update modified elements instead of recreating all DOM nodes
Preserve DOM state (like focus or form input values) when items move
Key Syntax
<!-- Using a property as the key -->
<ul>
<li repeat.for="item of items; key.bind: item.id">
${item.name}
</li>
</ul>
<!-- Using a literal property name -->
<ul>
<li repeat.for="item of items; key: id">
${item.name}
</li>
</ul>
Use unique, stable identifiers as keys. Avoid array indices if the collection order can change.
Contextual Properties
Inside a repeat.for
block, these contextual properties are available:
$index
- Zero-based index of the current item$first
- True for the first item$last
- True for the last item$even
/$odd
- True for even/odd indices$length
- Total number of items$parent
- Reference to the parent binding context
Example Usage
<ul>
<li repeat.for="item of items">
Index: ${$index} — Name: ${item.name} <br>
Is first? ${$first} | Is last? ${$last} <br>
Even? ${$even} | Odd? ${$odd} <br>
Total items: ${$length}
</li>
</ul>
Access parent context in nested repeats:
<div repeat.for="category of categories">
<div repeat.for="item of category.items">
Category ${$parent.$index}, Item ${$index}: ${item.name}
</div>
</div>
Working with Arrays
Arrays are the most common data source for repeats. Here’s an example component and its template:
Component (my-component.ts):
export class MyComponent {
items = [
{ name: 'John' },
{ name: 'Bill' }
];
}
Template (my-component.html):
<ul>
<li repeat.for="item of items">
${item.name}
</li>
</ul>
Aurelia tracks array changes when you use methods like push
, pop
, or splice
. Direct index assignments won't trigger updates.
Generating Ranges
repeat.for
can generate a sequence of numbers by specifying a number:
<p repeat.for="i of 5">
Item ${i}
</p>
This creates 5 paragraphs with i
ranging from 0 to 4.
Iterating Sets
Sets are handled much like arrays. The syntax remains the same, though the underlying collection is a Set
.
Component (repeater-template.ts):
export class RepeaterTemplate {
friends: Set<string> = new Set(['Alice', 'Bob', 'Carol', 'Dana']);
}
Template (repeater-template.html):
<template>
<p repeat.for="friend of friends">
Hello, ${friend}!
</p>
</template>
Iterating Maps
Maps offer a powerful way to iterate key-value pairs. Aurelia lets you deconstruct the map entry directly in the template.
Component (repeater-template.ts):
export class RepeaterTemplate {
friends = new Map([
['Hello', { name: 'Alice' }],
['Hola', { name: 'Bob' }],
['Ni Hao', { name: 'Carol' }],
['Molo', { name: 'Dana' }]
]);
}
Template (repeater-template.html):
<p repeat.for="[greeting, friend] of friends">
${greeting}, ${friend.name}!
</p>
Here, [greeting, friend]
splits each map entry so you can access both the key (greeting) and value (friend).
Iterating Objects via Value Converters
Objects aren’t directly iterable in Aurelia. To iterate over an object’s properties, convert it into an iterable format using a value converter.
Creating a Keys Value Converter
// resources/value-converters/keys.ts
export class KeysValueConverter {
toView(obj: object): string[] {
return Reflect.ownKeys(obj) as string[];
}
}
Using the Converter in a Template
<import from="resources/value-converters/keys"></import>
<p repeat.for="key of friends | keys">
${key}, ${friends[key].name}!
</p>
The keys
converter transforms the object into an array of its keys, making it iterable by repeat.for
.
Custom Collection Handling with Repeat Handlers
Aurelia's repeat system is extensible. You can create custom repeat handlers for non-standard collections by implementing the IRepeatableHandler
interface.
Custom Handler Example
import { IRepeatableHandler } from 'aurelia';
class ArrayLikeHandler implements IRepeatableHandler {
handles(value: unknown): boolean {
return typeof value === 'object' && value !== null && 'length' in value;
}
iterate(value: ArrayLike<unknown>, func: (item: unknown, index: number, collection: ArrayLike<unknown>) => void): void {
for (let i = 0; i < value.length; i++) {
func(value[i], i, value);
}
}
}
Register your handler during application configuration:
import { Registration } from 'aurelia';
Aurelia.register(
Registration.singleton(IRepeatableHandler, ArrayLikeHandler)
).app(MyApp).start();
Summary
The repeat.for
binding supports arrays, sets, maps, ranges, and custom collections. Use keyed iteration for optimal performance, and leverage contextual properties like $index
, $first
, and $parent
when needed.
Last updated
Was this helpful?