Skip to content

ResultGrid

<caos-result-grid>

a complete query result set, sorted and paged in the browser, with record ids that open

May be placed on a page inside an app.

Name Attribute Description Type Default Required
columns property only The columns: { key, label, sortable?, align?, width? }[] — the table’s own column shape, so nothing is transliterated. Columns are sortable unless a column says sortable: false, which is the opposite default from the table: everything in a result set in hand can be ordered, and requiring a flag per column would mean most of them silently could not be. json empty list Optional
rows property only The whole result set, each row a map of column key to value. Setting it clears the sort and returns to page 1 — staying on page 7 of the previous result would show an empty grid and let somebody conclude their query returned nothing. json empty list Optional
page page, also a property Which page is on screen, 1-based. Clamped into the pages that exist. number 1 Optional
pageSize page-size, markup only How many rows to a page. number 50 Optional
idColumns id-columns, markup only A comma-separated list of column keys holding record ids. Cells in those columns become real buttons raising caos-result-open-record. The component never builds a URL, which is what keeps it usable by an application whose records live somewhere it has not heard of. text none declared Optional
tookMs took-ms, markup only How long the query took, shown beside the row count. number none declared Optional
truncated truncated, markup only More rows matched than were returned. The summary says so, because “2,000 rows” over a capped set tells somebody their query matched exactly two thousand things. boolean false Optional
exportLabel export-label, markup only What the export button is called. text Export Optional
Name When it fires What it carries
caos-result-sort A column header is pressed. The rows are ALREADY reordered when this fires. { column, direction } — for a host that wants to remember the preference, not act on it.
caos-result-page The page changes through Previous or Next. { page, pageCount }.
caos-result-export The export button is pressed. { columns, rows } — the WHOLE set in the order shown, not the page. Writing the file is the application’s, because a component cannot know whether this page may start a download.
caos-result-open-record A record id cell is pressed. { id, row }.

Not documented yet — this piece has not said.

Not documented yet — this piece has not said.

Not documented yet — this piece has not said.

Name Type What it tells you
ordered row[] The whole set in the order being shown — every page, not the one on screen.
visibleRows row[] Just the rows on the current page.
pageCount number How many pages the set makes. An empty result is one page, never zero.
Part Which piece of it When it is there
::part(grid) The outer column. Always
::part(summary) The row count and timing line. Always
::part(table) The composed data table. Always
::part(footer) The pager and export row. Always
::part(pager) The Previous / Next cluster. Always
::part(page-status) The “Page 2 of 7” text. Always
::part(export) The export button. Always

When the WHOLE set of rows is already in hand — a query result, a comparison, an import preview — and sorting or paging it should not involve going back to the server.

  • DataTable — the rows are one server-held page of a larger set. The table raises a sort request and orders nothing, which is the right behaviour there and the wrong one here.
  • TestResultTable — the rows are test results — that component knows what a failure and a stack trace are.

The summary and the page position are both role="status" live regions: running a query and turning a page are the two moments when everything on screen changes, and neither moves focus, so neither would otherwise be announced. Record ids are <button> elements with an accessible name reading “Open record ” — a bare id read aloud says nothing about being able to press it. Sorting is announced by the composed table’s own aria-sort. An empty cell is drawn empty rather than as the word “null”, which is the shape of the transport rather than the state of the data.

Rows in hand: press a header and they reorder here, with no request and no risk of a re-run returning something different.

{
"id": "example",
"section": "A query result",
"columns": 1,
"items": [
{
"id": "result_grid_1",
"type": "component",
"key": "result_grid",
"inputs": {
"id_columns": "id",
"took_ms": 310,
"page_size": 3,
"columns": [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
},
{
"key": "industry",
"label": "Industry"
},
{
"key": "employees",
"label": "Employees",
"align": "end"
}
],
"rows": [
{
"id": "001x00000A1b2C",
"name": "Northwind Traders",
"industry": "Retail",
"employees": 420
},
{
"id": "001x00000A1b2D",
"name": "Contoso Marine",
"industry": "Shipping",
"employees": 1180
},
{
"id": "001x00000A1b2E",
"name": "Fabrikam Metals",
"industry": null,
"employees": 95
},
{
"id": "001x00000A1b2F",
"name": "Tailspin Air",
"industry": "Aviation",
"employees": 3300
}
]
}
}
]
}
<caos-result-grid id="resultGrid1" id-columns="id" took-ms="310" page-size="3"></caos-result-grid>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const resultGrid1 = document.getElementById('resultGrid1');
resultGrid1.columns = [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
},
{
"key": "industry",
"label": "Industry"
},
{
"key": "employees",
"label": "Employees",
"align": "end"
}
];
resultGrid1.rows = [
{
"id": "001x00000A1b2C",
"name": "Northwind Traders",
"industry": "Retail",
"employees": 420
},
{
"id": "001x00000A1b2D",
"name": "Contoso Marine",
"industry": "Shipping",
"employees": 1180
},
{
"id": "001x00000A1b2E",
"name": "Fabrikam Metals",
"industry": null,
"employees": 95
},
{
"id": "001x00000A1b2F",
"name": "Tailspin Air",
"industry": "Aviation",
"employees": 3300
}
];

More matched than came back. The summary says so, rather than reporting the cap as if it were the answer.

{
"id": "example",
"section": "A capped result",
"columns": 1,
"items": [
{
"id": "result_grid_1",
"type": "component",
"key": "result_grid",
"inputs": {
"truncated": true,
"took_ms": 2140,
"columns": [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
}
],
"rows": [
{
"id": "001x00000A1b2C",
"name": "Northwind Traders"
},
{
"id": "001x00000A1b2D",
"name": "Contoso Marine"
}
]
}
}
]
}
<caos-result-grid id="resultGrid1" truncated took-ms="2140"></caos-result-grid>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const resultGrid1 = document.getElementById('resultGrid1');
resultGrid1.columns = [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
}
];
resultGrid1.rows = [
{
"id": "001x00000A1b2C",
"name": "Northwind Traders"
},
{
"id": "001x00000A1b2D",
"name": "Contoso Marine"
}
];

Zero rows is a result, not an error. The grid says so, the export button is disabled because there is nothing to export, and the pager reads page 1 of 1.

{
"id": "example",
"section": "A query that matched nothing",
"columns": 1,
"items": [
{
"id": "result_grid_1",
"type": "component",
"key": "result_grid",
"inputs": {
"took_ms": 88,
"columns": [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
}
],
"rows": []
}
}
]
}
<caos-result-grid id="resultGrid1" took-ms="88"></caos-result-grid>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const resultGrid1 = document.getElementById('resultGrid1');
resultGrid1.columns = [
{
"key": "id",
"label": "Id"
},
{
"key": "name",
"label": "Name"
}
];
resultGrid1.rows = [];