Tree API ServerSide DataProvider
The CAPITreeServerDataProvider connects the ServerSide tree logic with the RequestProvider to seamlessly interact with remote server endpoints expecting node expansion queries.
Designed to power TreeViews and hierarchical structures by automatically pushing route queries to backend API structures.
Extends: Tree ServerSide DataProvider
Uses: RequestProvider
// --- Client Side (Vue) ---
import { CAPITreeServerDataProvider } from '@katlux/providers/data'
const provider = new CAPITreeServerDataProvider({
cacheStrategy: 'Memory',
cacheLifetime: 30000
})
await provider.setAPIUrl('/api/v1/taxonomy')
// --- Server Side (Nuxt Nitro) ---
// server/api/v1/taxonomy.get.ts
export default defineEventHandler(async (event) => {
const query = getQuery(event)
// The provider automatically sends these parameters as URL query strings:
// pageNumber — number string — current page (e.g. "1"), parse with parseInt
// pageSize — number string — items per page (e.g. "10"), parse with parseInt
// sortList — IDataSort[] serialized as JSON string — deserialize with JSON.parse
// filter — IDataFilter serialized as JSON string — deserialize with JSON.parse
// expandedNodes — (string | number)[] serialized as JSON string — deserialize with JSON.parse
// parentKey — string — field name for parent reference (e.g. "parentId")
// idKey — string — field name for unique node ID (e.g. "id")
// paginateBy — TreePaginationMode string — "all" or "root"
// expandedByDefault — boolean string — "true" or "false", compare with === 'true'
const pageNumber = parseInt(query.pageNumber as string) || 1
const pageSize = parseInt(query.pageSize as string) || 10
const sortList = query.sortList ? JSON.parse(query.sortList as string) : []
const filter = query.filter ? JSON.parse(query.filter as string) : null
const expandedNodes = query.expandedNodes ? JSON.parse(query.expandedNodes as string) : []
const parentKey = (query.parentKey as string) ?? 'parentId'
const idKey = (query.idKey as string) ?? 'id'
const paginateBy = (query.paginateBy as string) ?? 'all'
const expandedByDefault = query.expandedByDefault === 'true'
// Apply the parameters to your database / ORM layer
const { rows, count } = await fetchNestedTaxonomy(expandedNodes, pageNumber, pageSize)
// Return shape must be: { rows: Array<any>, rowCount: number }
// rows: flat array of root nodes + children of expanded nodes only
return {
rows: rows,
rowCount: count
}
})Configuration for server-side hierarchical data management.
| Property | Type | Default | Description |
|---|---|---|---|
| idKey | string | 'id' | The unique identifier field for each node |
| parentKey | string | 'parentId' | The field used to establish parent-child relationships |
| expandedByDefault | boolean | false | Whether nodes are expanded by default on the server |
| paginateBy | 'all' | 'root' | 'all' | Mode for server-side pagination (all visible nodes vs only roots) |
| pageSize | number | 10 | Items per page (sent to API) |
| currentPage | number | 1 | Initial page index (sent to API) |
| SSR | boolean | false | Enables useAsyncData integration |
| deduplicate | boolean | true | Prevents duplicate recursive API calls |
State and methods for controlling server-side tree expansion.
| Name | Type | Description |
|---|---|---|
| toggleNode | (id: string | number) => void | Updates expansion set and triggers a server reload |
| expand / collapse | (id: string | number) => void | Explicit control for node expansion state |
| collapseAll | () => void | Clears all expanded nodes and reloads roots |
| rowCount | Ref<number> | Total visible nodes reported by the server result |
| pageData | Ref<any[]> | Current slice of already-processed hierarchical records |
| setAPIUrl | (url: string) => Promise<void> | Sets URL and initializes server-side pagination handler |
| setPageDataHandler | (handler: TTreePageDataHandler) => void | Overrides the default HTTP API fetch handler with custom tree loading logic. |
| refresh | (hardRefresh?: boolean) => Promise<void> | Re-runs data request. Cache will only be overridden if hardRefresh is true. |
| loadPageData | (opts?: { disableCache? }) => Promise<void> | Re-runs the request with current expandedNodes set |
| delete | (items: any[]) => Promise<void> | Sends a DELETE request and invalidates the tree cache on success |
The provider automatically appends these parameters to every GET request. The first four are shared with flat providers; the remaining five are tree-specific and control server-side hierarchy expansion.
// Full URL example:
// GET /api/v1/taxonomy?pageNumber=1&pageSize=10&sortList=[...]&filter={...}&expandedNodes=[1,4]&parentKey=parentId&idKey=id&paginateBy=all&expandedByDefault=false| Parameter | Type (after parsing) | Example value | Description |
|---|---|---|---|
| pageNumber | number | 1 | Current page index, starting at 1. Parse with parseInt. |
| pageSize | number | 10 | Number of records to return for the page. Parse with parseInt. |
| sortList | IDataSort[] (JSON string) | [{"field":"name","direction":"asc"}] | JSON-serialized sort descriptors. Deserialize with JSON.parse. Empty array [] when no sort is applied. |
| filter | IDataFilter (JSON string) | {"active":true} | JSON-serialized filter object. Deserialize with JSON.parse. null when no filter is active. |
| expandedNodes | (string | number)[] (JSON string) | [1, 4, 15] | JSON array of node IDs currently expanded by the user. Use this to fetch and return only root nodes plus children of these IDs. |
| parentKey | string | "parentId" | The field name used for parent references in the row objects. Configurable via constructor. |
| idKey | string | "id" | The field name used as the unique node identifier. Configurable via constructor. |
| paginateBy | 'all' | 'root' | "all" | Pagination mode. 'all' counts all visible nodes; 'root' counts only root-level nodes. |
| expandedByDefault | boolean (string) | "false" | Whether all nodes should be treated as expanded. Compare with === 'true' after parsing. |
// IDataSort shape
interface IDataSort {
field: string
direction: 'asc' | 'desc'
}
// IDataFilter shape
interface IDataFilter {
[key: string]: any
}Each row returned by the API must be a plain, flat object. Tree hierarchy is built from two fields: a unique node identifier and a parent reference. Root nodes must have null (or an absent value) for their parent field.
// Flat array returned by the server — hierarchy is derived from id/parentId
{
rowCount: 5,
rows: [
{ id: 1, parentId: null, name: 'Root Category' },
{ id: 2, parentId: 1, name: 'Sub Category A' },
{ id: 3, parentId: 1, name: 'Sub Category B' },
{ id: 4, parentId: 2, name: 'Leaf Node' },
{ id: 5, parentId: null, name: 'Another Root' }
]
}The id and parentId field names are configurable via the idKey and parentKey constructor options.