$npx -y skills add DevExpress/agent-skills --skill devextreme-datasourceHelp developers configure the DevExtreme data layer: DataSource, ArrayStore, LocalStore, ODataStore, and CustomStore. Use when someone asks about binding components to data, loading data from a REST API, configuring an OData endpoint, implementing a custom data source, client-sid
| 1 | # DevExtreme Data Layer Skill |
| 2 | |
| 3 | A skill for configuring the DevExtreme data layer: `DataSource`, `ArrayStore`, `LocalStore`, `ODataStore`, and `CustomStore`. |
| 4 | |
| 5 | ## When to Use This Skill |
| 6 | |
| 7 | - Binding a component (`dataSource` property) to a plain array, a URL, or a Store |
| 8 | - Configuring paging, sorting, filtering, and grouping at the DataSource level |
| 9 | - Connecting to an OData endpoint |
| 10 | - Implementing a `CustomStore` to load data from any REST API |
| 11 | - Implementing `insert`, `update`, `remove` in a `CustomStore` for editable components (DataGrid, etc.) |
| 12 | - Deciding between client-side and server-side data processing modes |
| 13 | |
| 14 | ## Before You Start |
| 15 | |
| 16 | > ⚠️ **Always use DevExtreme's `CustomStore`, `DataSource`, or a built-in Store (`ArrayStore`, `ODataStore`) for data binding. Never replace them with raw `fetch`/`axios`, react-query, SWR, or any other data-fetching library. For user-visible error notifications, always use `notify` from `devextreme/ui/notify`.** |
| 17 | |
| 18 | ## Architecture Overview |
| 19 | |
| 20 | ```text |
| 21 | UI Component |
| 22 | └── DataSource — orchestrates paging, sorting, grouping, filtering |
| 23 | └── Store — handles raw data access (CRUD) |
| 24 | ├── ArrayStore — in-memory array |
| 25 | ├── LocalStore — HTML5 localStorage |
| 26 | ├── ODataStore — OData v2/v3/v4 endpoint |
| 27 | └── CustomStore — any backend (REST, GraphQL, etc.) |
| 28 | ``` |
| 29 | |
| 30 | A component's `dataSource` property accepts: |
| 31 | - A **plain array** — DevExtreme wraps it in an `ArrayStore` + `DataSource` automatically. |
| 32 | - A **URL string** — DevExtreme fetches JSON and wraps it in a `DataSource`. |
| 33 | - A **Store instance** — passed directly or wrapped in a `DataSource`. |
| 34 | - A **DataSource instance** — gives full control over paging, sorting, grouping. |
| 35 | - A **DataSource config object** — DevExtreme constructs the `DataSource` for you. |
| 36 | |
| 37 | ## Documentation Reference Files |
| 38 | |
| 39 | | File | When you need to | |
| 40 | |---|---| |
| 41 | | [references/stores.md](references/stores.md) | Use ArrayStore, LocalStore, or ODataStore | |
| 42 | | [references/custom-store.md](references/custom-store.md) | Implement CustomStore for any REST/custom backend | |
| 43 | | [references/datasource-options.md](references/datasource-options.md) | Configure DataSource-level options: paging, sort, filter, group, map, postProcess | |
| 44 | |
| 45 | ## Key API Summary |
| 46 | |
| 47 | ### DataSource options (most used) |
| 48 | |
| 49 | | Option | Type | Description | |
| 50 | |---|---|---| |
| 51 | | `store` | `Store \| StoreConfig` | The underlying store | |
| 52 | | `filter` | `Filter` | Static client-side filter applied on load | |
| 53 | | `sort` | `Sort` | Default sort order | |
| 54 | | `group` | `Group` | Default grouping | |
| 55 | | `paginate` | `Boolean` | Enables paging (default `true` for most components) | |
| 56 | | `pageSize` | `Number` | Items per page (default `20`) | |
| 57 | | `requireTotalCount` | `Boolean` | Requests total item count alongside data | |
| 58 | | `reshapeOnPush` | `Boolean` | Triggers UI re-render on `push()` calls | |
| 59 | | `searchExpr` | `String \| Array` | Fields to search against | |
| 60 | | `searchValue` | `any` | Search value | |
| 61 | | `select` | `Array` | Field projection | |
| 62 | | `map` | `function(item)` | Transforms each item after load | |
| 63 | | `postProcess` | `function(data)` | Transforms the full loaded dataset | |
| 64 | |
| 65 | ### Store base options (all stores) |
| 66 | |
| 67 | | Option | Description | |
| 68 | |---|---| |
| 69 | | `key` | Primary key field name(s) | |
| 70 | | `onLoaded` | Fires after data is loaded | |
| 71 | | `onInserting` / `onInserted` | Fires before/after insert | |
| 72 | | `onUpdating` / `onUpdated` | Fires before/after update | |
| 73 | | `onRemoving` / `onRemoved` | Fires before/after remove | |
| 74 | | `errorHandler` | Global error handler for store operations | |
| 75 | |
| 76 | ## Quick-Start Patterns |
| 77 | |
| 78 | ### Plain array (simplest) |
| 79 | |
| 80 | ```ts |
| 81 | // Any framework — just pass the array |
| 82 | dataSource = [ |
| 83 | { id: 1, name: 'Alice' }, |
| 84 | { id: 2, name: 'Bob' } |
| 85 | ]; |
| 86 | // In template / options: dataSource={dataSource} or [dataSource]="dataSource" |
| 87 | ``` |
| 88 | |
| 89 | ### ArrayStore with a DataSource |
| 90 | |
| 91 | ```ts |
| 92 | import ArrayStore from 'devextreme/data/array_store'; |
| 93 | import DataSource from 'devextreme/data/data_source'; |
| 94 | |
| 95 | const store = new ArrayStore({ |
| 96 | key: 'id', |
| 97 | data: [ |
| 98 | { id: 1, name: 'Alice' }, |
| 99 | { id: 2, name: 'Bob' } |
| 100 | ] |
| 101 | }); |
| 102 | |
| 103 | const dataSource = new DataSource({ |
| 104 | store, |