Home/Data & State/Static Data
Data & State

Static Data

Use a simple in-memory array without any server calls. Ideal for prototypes, reference tables, or small datasets that don't need pagination.

The smallest data source

An object with one method, returning of(array). No HTTP, no async, no configuration beyond a height.

#
Name
Category
Price
Stock
SKU
1
Wireless Headphones
Electronics
79.99
143
EL-0001
2
Ergonomic Chair
Furniture
349
28
FU-0002
3
Mechanical Keyboard
Electronics
129.95
67
EL-0003
4
Standing Desk
Furniture
499
12
FU-0004
5
USB-C Hub
Accessories
39.99
210
AC-0005
6
Monitor Arm
Accessories
59
54
AC-0006
7
4K Webcam
Electronics
149
38
EL-0007
8
Desk Lamp
Furniture
49.99
91
FU-0008
9
Laptop Stand
Accessories
34.95
175
AC-0009
10
Noise-Cancel Mic
Electronics
89.99
44
EL-0010
All records loaded
10 / 10 records

Sorting and filtering, without writing either

Click a header or type in the filter row. The data source below sorts nothing and filters nothing — with sortMode and filterApplyMode set to 'client', the grid does both over the rows it already has.

What the grid last asked the source to sort by: [] (empty)

Name
Category
Price
Stock
Wireless Headphones
Electronics
79.99
143
Ergonomic Chair
Furniture
349
28
Mechanical Keyboard
Electronics
129.95
67
Standing Desk
Furniture
499
12
USB-C Hub
Accessories
39.99
210
Monitor Arm
Accessories
59
54
4K Webcam
Electronics
149
38
Desk Lamp
Furniture
49.99
91
Laptop Stand
Accessories
34.95
175
Noise-Cancel Mic
Electronics
89.99
44
All records loaded
10 / 10 records

Paging over the same array

The source slices with offset and limit and reports the total. That is the entire implementation — the pager comes from totalCount.

#
Name
Category
Price
Stock
SKU
1
Wireless Headphones
Electronics
79.99
143
EL-0001
2
Ergonomic Chair
Furniture
349
28
FU-0002
3
Mechanical Keyboard
Electronics
129.95
67
EL-0003
4
Standing Desk
Furniture
499
12
FU-0004
1–4 of 10

No data source at all

This grid has no [dataSource] binding. It starts empty and every row arrives through grid.applyTransaction() — the shape to use when your data is pushed to you rather than pulled by the grid.

Rows pushed so far: 0

#
Name
Category
Price
Stock
SKU

Nothing here yet — press Add a row.

Try adjusting your filters or search criteria.

How it works

The grid's dataSource input expects an object with a fetchRows(params) method that returns an Observable<{ rows: T[]; totalCount: number }>. For in-memory arrays, wrapping the result with RxJS of() satisfies that contract without any async calls.

The grid calls fetchRows() on the initial load, every page change, every sort change, and every filter change. Your implementation decides how to respond to each FetchParams:

  • Use p.offset and p.limit to slice the array for paging.
  • Set sortMode: 'client' in config so the grid sorts the loaded rows in memory — no need to implement sorting in fetchRows(). The grid passes sorts: [] to avoid double-sorting.
  • For client-side filtering, inspect p.filters manually. For server-side data sources, serialize p.filters and send to the API — the grid doesn't apply filters itself (unless you implement it in fetchRows).

When to use static data

Static in-memory data works well for: configuration tables, reference lists, lookup data, editable grids where the full dataset fits in memory, and prototyping before the API is ready. For large server-side datasets, use a real HttpClient-based data source instead (see Infinite Scroll or Paging).

dataSource is optional

If [dataSource] is omitted entirely, the grid renders with zero rows and shows the empty state. This is useful when your data arrives via imperative transactions (grid.applyTransaction()) rather than through a pull-based data source.

With sortMode: 'client' the grid passes sorts: [] to fetchRows() and sorts the loaded rows itself — your data source only slices with offset/limit, no sort logic needed.

Data source contract

PropertyTypeDefaultDescription
dataSource.fetchRows()(params: FetchParams) => Observable<FetchResult<T>>—The only required data-source member — wrap an in-memory array with of() to satisfy it synchronously.
params.offset / params.limitnumber—Slice window for the current page: rows.slice(offset, offset + limit).
config.sortMode'server' | 'client''server'client sorts loaded rows in memory — no sort code in fetchRows().
config.scrollMode'infinite' | 'paging' | 'virtual-paging''infinite'This demo uses classic paging with pageSize: 5.
FetchResult.totalCountnumber—Total row count across all pages — drives the pager and scroll length.