List Rendering

Master list rendering in Aurelia with repeat.for. Learn efficient data binding, performance optimization, advanced patterns, and real-world techniques for dynamic collections including arrays, maps, s

The repeat.for binding is Aurelia's powerful list rendering mechanism that creates highly optimized, reactive displays of collection data. It intelligently tracks changes, minimizes DOM updates, and provides rich contextual information for sophisticated data presentation.

Core Concepts

The repeat.for Binding

repeat.for creates a template instance for each item in a collection, similar to a for...of loop but with intelligent DOM management:

<ul>
  <li repeat.for="item of items">
    ${item.name}
  </li>
</ul>

JavaScript Analogy:

for (let item of items) {
  // Aurelia creates DOM element for each item
  console.log(item.name);
}

Change Detection and Updates

Aurelia automatically observes collection changes and updates the DOM efficiently:

Important: Use array mutating methods (push, pop, splice, reverse, sort) for automatic detection. Direct index assignment works but requires the array reference to change for detection.

Performance Optimization with Keys

Why Keys Matter

Without keys, Aurelia recreates DOM elements when collections change. With keys, it reuses existing elements:

Key Strategies

Property-based keys (recommended):

Literal property keys (more efficient):

Expression-based keys (flexible but slower):

When to Use Keys

  • Dynamic collections where items are added, removed, or reordered

  • Form inputs to preserve user input during updates

  • Stateful components to maintain component state

  • Large lists for performance optimization

  • Sortable/filterable lists

Avoid keys when:

  • Collection is static or append-only

  • Items are simple primitives without DOM state

  • Performance testing shows no benefit

Contextual Properties

Every repeat iteration provides rich contextual information:

Complete Property Reference

Property
Type
Description

$index

number

Zero-based index (0, 1, 2...)

$first

boolean

true for the first item

$last

boolean

true for the last item

$middle

boolean

true for items that aren't first or last

$even

boolean

true for even indices (0, 2, 4...)

$odd

boolean

true for odd indices (1, 3, 5...)

$length

number

Total number of items

$previous

any

null

$parent

object

Parent binding context

Nested Repeats and $parent

Access parent contexts in nested structures:

Accessing Previous Items with $previous

The $previous contextual property provides access to the previous iteration's item, enabling powerful comparison and rendering patterns. It is a computed property available by default as part of repeat's contextual values. You can disable all contextual computed values (including $previous) using the contextual option.

Basic usage:

Key characteristics:

  • $previous is null for the first item

  • $previous is undefined when contextual is disabled

  • Computed property with minimal overhead when enabled (contextual is enabled by default)

  • Works with all collection types (arrays, Maps, Sets, etc.)

  • Compatible with keyed repeats

Section Headers and Dividers

A common use case is rendering section headers only when data changes:

Output:

Comparison and Change Indicators

Highlight changes from previous values:

Combining with Keys

$previous works seamlessly with keyed repeats:

Conditional Contextual Properties

Control contextual computed properties (including $previous) based on view model properties:

Performance Considerations

When contextual is disabled:

  • Zero memory overhead - $previous is not computed

  • Negligible CPU cost - single conditional check per item

When contextual is enabled (default):

  • Computed on demand via contextual getter

  • Minimal CPU cost

Best practices:

  • Keep contextual enabled unless you have a strong reason to disable it

  • If needed, disable per-instance with contextual: false or contextual.bind: someBoolean

Data Types and Collections

Arrays

The most common and optimized collection type:

Sets

Useful for unique collections:

Maps

Perfect for key-value pairs:

Number Ranges

Generate sequences quickly:

Advanced Patterns

Destructuring Declarations

Extract multiple values in the repeat declaration:

Integration with Other Template Controllers

Conditional rendering within repeats:

Nested conditionals and repeats:

Working with Async Data

Handle loading states and async operations:

Complex Object Iteration

Use value converters for non-standard collections:

Performance Best Practices

Optimizing Large Lists

Use keyed iteration:

Consider virtual scrolling for very large lists:

This requires using the virtual repeat plugin.

Memory Management

Avoid memory leaks in complex scenarios:

Custom Collection Handlers

Built-in Handlers

Aurelia includes handlers for:

  • Arrays (Array, [])

  • Sets (Set)

  • Maps (Map)

  • Numbers (5 → creates range 0-4)

  • Array-like objects (NodeList, HTMLCollection, etc.)

  • Null/undefined (renders nothing)

Creating Custom Handlers

For specialized collections:

Observable Collections

Create reactive custom collections:

Troubleshooting Common Issues

Issue: Changes Not Reflecting

Problem: Direct array index assignment doesn't trigger updates

Solution: Use array methods or replace the array

Issue: Form State Lost on Reorder

Problem: Input values disappear when list is reordered

Solution: Use stable keys

Issue: Performance with Large Lists

Problem: Slow rendering with 1000+ items

Solutions:

  1. Use virtual scrolling for very large lists

  2. Implement pagination or infinite scroll

  3. Optimize templates - minimize complex expressions

  4. Use keys to enable DOM reuse

Issue: Memory Leaks

Problem: Components not disposing properly

Solution: Clean up in lifecycle hooks

Real-World Examples

Dynamic Product Catalog

Data Table with Sorting

TypeScript Integration

Type-Safe Repeats

Last updated

Was this helpful?