Lazy Loading
Hand the tree a DataSource plus hasItemsExpr and children are fetched on demand — one parentId eq key request per expansion, cached until the sort changes or refresh() is called. A skeleton row shows while a level is in flight.
hasItemsExpr DataSource loadMode
350ms fake server per-expansion requests
Requests
parentId eq null
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { OgeTreeList } from '@oge-ui/tree-list';
import { CustomDataSource } from '@oge-ui/core';
interface Node {
id: number;
parentId: number | null;
name: string;
hasReports: boolean;
}
@Component({
selector: 'demo-root',
imports: [OgeTreeList],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- children are fetched per expansion:
load({ filter: ['parentId', '=', parentKey] }) -->
<oge-tree-list
[data]="source"
keyExpr="id"
parentIdExpr="parentId"
hasItemsExpr="hasReports"
/>
`,
})
export class Demo {
protected readonly source = new CustomDataSource<Node>({
key: 'id',
load: (options) =>
fetch(`/api/org?parent=${parentKeyOf(options)}`)
.then((response) => response.json())
.then((data: Node[]) => ({ data, totalCount: data.length })),
});
}
/** The tree list asks for one level at a time: ['parentId', '=', key]. */
function parentKeyOf(options: { filter?: unknown }): string {
const filter = options.filter as [string, string, unknown] | undefined;
return String(filter?.[2] ?? '');
}Notes
- The initial load asks for
parentId eq rootValue; an OData backend works without any adapter code ($filter=parentId eq 42). hasItemsExprdecides expandability before children exist locally.- Lazy mode needs a string
parentIdExpr; a sort change re-requests open levels. loadModedefaults to'lazy'exactly when a DataSource andhasItemsExprare both present — set it explicitly to override.