Skip to Content

Collection

Eager collection class for one-to-many relationships. Holds array of loaded models.

Import

import { Collection } from '@gluonic/client'

Class Signature

class Collection<T> { // Constructor constructor(items?: T[]) // Properties get length(): number // Methods at(index: number): T | undefined map<U>(fn: (item: T, i: number) => U): U[] forEach(fn: (item: T, i: number) => void): void filter(fn: (item: T, i: number) => boolean): T[] find(fn: (item: T, i: number) => boolean): T | undefined toArray(): T[] push(item: T): number }

Note: Collection is eager - all items are loaded immediately. For lazy loading, use LazyCollection.


Constructor

constructor(items?: T[])

Create a collection with optional initial items.

Parameters:

ParameterTypeDescription
itemsT[]Optional initial array

Example:

// Empty collection const comments = new Collection<Comment>() // With initial items const comments = new Collection<Comment>([comment1, comment2])

Properties

length

get length(): number

Number of items in the collection.

Returns: number - Count of items

Reactive: Updates when items are added/removed

Example:

const TaskList = observer(({ project }) => { return <div>{project.tasks.length} tasks</div> })

Methods

at()

at(index: number): T | undefined

Get item at specific index.

Parameters:

ParameterTypeDescription
indexnumberZero-based index

Returns: T | undefined - Item at index or undefined

Example:

const firstTask = project.tasks.at(0) const lastTask = project.tasks.at(-1) // Negative index from end

map()

map<U>(fn: (item: T, i: number) => U): U[]

Transform each item.

Parameters:

ParameterTypeDescription
fn(item, i) => UTransform function

Returns: U[] - Transformed array

Example:

const TaskList = observer(({ project }) => { return ( <div> {project.tasks.map((task, i) => ( <TaskCard key={task.id} task={task} index={i} /> ))} </div> ) })

forEach()

forEach(fn: (item: T, i: number) => void): void

Iterate over each item.

Parameters:

ParameterTypeDescription
fn(item, i) => voidCallback for each item

Example:

project.tasks.forEach((task, i) => { console.log(`${i}: ${task.title}`) })

filter()

filter(fn: (item: T, i: number) => boolean): T[]

Get items matching predicate.

Parameters:

ParameterTypeDescription
fn(item, i) => booleanFilter function

Returns: T[] - Filtered array

Example:

const DoneTaskList = observer(({ project }) => { const doneTasks = project.tasks.filter(task => task.done) return <div>{doneTasks.length} done</div> })

find()

find(fn: (item: T, i: number) => boolean): T | undefined

Find first item matching predicate.

Parameters:

ParameterTypeDescription
fn(item, i) => booleanSearch function

Returns: T | undefined - First match or undefined

Example:

const urgentTask = project.tasks.find(task => task.priority === 'urgent')

toArray()

toArray(): T[]

Get copy of items as plain array.

Returns: T[] - Copy of items

Example:

const taskArray = project.tasks.toArray() console.log(taskArray.length)

push()

push(item: T): number

Add item to collection.

Parameters:

ParameterTypeDescription
itemTItem to add

Returns: number - New length

Example:

project.tasks.push(newTask)

Usage

In Model Definitions

Use Collection for eager relationships (all items loaded immediately):

@ClientModel('project') export class Project extends Model { @Property() id = crypto.randomUUID() @Property() title = '' // Collection (eager) - all tasks loaded immediately @OneToMany('task', 'project') tasks = new Collection<Task>() }

Runtime: At runtime, @OneToMany decorator transforms this to LazyCollection<Task> for lazy loading. The clean type signature Collection<Task> is preserved for TypeScript.

In Components

const ProjectDetail = observer(({ project }) => { return ( <div> <h1>{project.title}</h1> <p>{project.tasks.length} tasks</p> <ul> {project.tasks.map(task => ( <li key={task.id}>{task.title}</li> ))} </ul> </div> ) })

Collection vs LazyCollection

FeatureCollectionLazyCollection
LoadingEager (all items immediately)Lazy (loads when accessed)
Initial stateItems provided in constructorEmpty until hydrated
NetworkNo automatic fetchingAuto-fetches on first access
Use caseSmall, pre-loaded setsRelationships, large sets

Recommendation: Use LazyCollection for relationships (default behavior with decorators).


Examples

Filtering

const ActiveTasks = observer(({ project }) => { const activeTasks = project.tasks.filter(task => !task.done) return ( <div> <h2>Active Tasks ({activeTasks.length})</h2> {activeTasks.map(task => ( <TaskCard key={task.id} task={task} /> ))} </div> ) })

Sorting

const SortedTasks = observer(({ project }) => { const sortedTasks = project.tasks .toArray() .sort((a, b) => a.title.localeCompare(b.title)) return ( <ul> {sortedTasks.map(task => ( <li key={task.id}>{task.title}</li> ))} </ul> ) })

Computed Stats

const TaskStats = observer(({ project }) => { const total = project.tasks.length const done = project.tasks.filter(t => t.done).length const progress = total > 0 ? (done / total) * 100 : 0 return ( <div> <p>{done} of {total} complete</p> <ProgressBar value={progress} /> </div> ) })

See Also

Last updated on