Skip to content

Wire a page's data

What you're doing

You have a page with a core.grid block and it shows zero rows and no error message. This is the single most common confusion on the platform. This guide explains the one chain that connects a grid to a table.

The mental model

page.metadata.dataSource   ──names──▶   a Data Provider file      ──points at──▶   a REST base path
"oeq-equipment-provider"                metadata/provider/          /api/v1/entities/oeq_equipment/records

Three things must line up exactly:

  1. The page's top-level metadata.dataSource is a string.
  2. That string equals the name field of a file in spk-assembly/metadata/provider/.
  3. That provider's definition.basePath is a real REST path that supports search.

The grid block itself has no data configuration. It renders whatever the page's dataSource provider returns.

The complete example

Page (equipment-register.json), last two lines of the file:

json
  "metadata": { "dataSource": "oeq-equipment-provider" },
  "modules": ["office-equipment"]
}

Provider (spk-assembly/metadata/provider/oeq-equipment-provider.json) — the real file:

json
{
  "name": "oeq-equipment-provider",
  "description": "Data Provider for oeq_equipment (grid + CRUD).",
  "definition": {
    "kind": "rest",
    "connectionRef": "self",
    "basePath": "/api/v1/entities/oeq_equipment/records",
    "supports": ["search", "get", "create", "update"]
  },
  "metadata": {},
  "modules": []
}

The string "oeq-equipment-provider" appears in both files, spelled identically. That is the whole wiring.

Line by line

  • metadata.dataSource — page-level. Not inside definition, not on any block. A grid with no matching dataSource shows nothing.
  • provider name — the lookup key. Must match dataSource character for character.
  • kind: "rest" — the provider calls a REST endpoint.
  • connectionRef: "self" — this ERP's own backend. (External systems use a named connection.)
  • basePath — for an entity you own, it's always /api/v1/entities/<entityName>/records. The Entity Engine serves search at <basePath>/query, get at <basePath>/{id}, create at POST <basePath>, update at PUT <basePath>/{id}.
  • supports — which of those the grid/dialogs may use.

Filtering the grid

The grid's externalFilter property binds a page state object. Its keys become query filters:

json
"externalFilter": { "source": "binding", "binding": { "scope": "page", "key": "gridExternalFilter" } }

A search input then writes into it:

json
"events": { "committed": { "source": "action-chain", "actions": [
  { "id": "a0", "order": 0, "type": "setValue",
    "config": { "field": "page.gridExternalFilter.search", "value": "${event.new}" } }
] } }

Now typing in the box filters the grid on search; picking a status filters on status. (${event.new} — the committed value — see Add a create/edit form.)

Refreshing the grid after a write

Bind refreshTrigger to a page value and flip it at the end of a save chain:

json
{ "id": "a2", "order": 2, "type": "setValue",
  "config": { "field": "page.gridRefreshTick", "value": "${!page.gridRefreshTick}" } }

When you need a computed / joined read

If the grid needs columns from more than one table, or server-side aggregation, the provider's basePath can point at a Data Service or Data View instead of a raw entity. See Add a data provider, data view, or data service.

How to verify it worked

The semantic linter catches the mismatch before you publish:

bash
erp plugin test office-equipment/spk-assembly

If the wiring is broken you get:

PAGE-DS-001  equipment-register.json: core.grid present but metadata.dataSource
             "oeq-equipmnt-provider" does not match any metadata/provider/*.json name

When it's right, erp plugin test is silent on PAGE-DS-001 and after publish:

bash
erp api get "/api/v1/entities/oeq_equipment/records/query?size=3"

returns real rows — which is exactly what the grid will show.

Common mistakes

SymptomCauseFix
grid empty, no errordataSource typo / absent / put on the grid blockmove it to page metadata.dataSource, match the provider name
grid empty but the entity has rowsprovider basePath wrongfor your own entity it's /api/v1/entities/<name>/records
grid loads once, never refreshes after saveno refreshTrigger bindingbind it and toggle it at the end of the save chain
filter box does nothingexternalFilter not bound, or committed writes the wrong keybind gridExternalFilter; write page.gridExternalFilter.<key>
"0 rows" only for some usersrow-level permissionsexpected — check the user's role