api reference
List API Reference
type: 'list': many values in one cell, each usable on its own - chips, a token editor, "any item matches" filters and four list operators.
API reference › The list module
All 18 pages Everything on one page → Developer guide →
Lists: the list module
import '@toclocoinc/lattice-grid/modules/list';
Importing the module registers the list data type with the page's registry
(listModule is the module object, for a grid built on a registry of its own).
Without it, type: 'list' warns type:list, naming this import, and the
column is plain text.
A list column holds many values in one cell, each usable on its own: the tags on a
ticket, the sizes a product comes in, the dates a meeting recurs on.
typeOptions: { of } names the item type - any scalar data type,
'text' by default - and each item is read, formatted, parsed and compared as
a value of that type. A name that is not a known scalar type warns once by name
(type:of:<name>) and the items are text. A cell is an array of items;
null and [] are both an empty cell. A single value where a list was
expected is read as a one-item list and list:scalar:<column> says so once;
an item the item type cannot read is left out of the stored list and
list:item:<column> names it. Neither rewrites your row object.
columns: [
{ field: 'tags', type: 'list' }, // items are text
{ field: 'sizes', type: 'list', typeOptions: { of: 'number', joiner: '; ' } },
]
Display, editing, copying. A cell draws its items as chips in the list's order;
the ones that do not fit the column's width collapse into a +3 chip, and the
cell's tooltip lists every item. Each item is shown through the item type's own formatter. The
editor is a token editor: type and press Enter to add an item, Backspace in the empty box removes
the last one, and a pasted comma-separated string becomes one item per piece. Each piece is read
by the item type's parser, and one it cannot read is refused by name and not stored. The edit
goes through the ordinary edit contract, events and undo. Copy, CSV and Excel write the items
joined by ', ', or by the column's joiner
(typeOptions: { joiner: '; ' }); typed and pasted text is split on it and on
commas.
Filtering on a list
One item at a time. Every operator the item type offers applies to a
list column, and a row matches when any item does: eq 'gold' keeps
a row whose list holds gold, contains 'ab' one with an item containing it,
gt 5 on a list of numbers one with an item above five. The negations - ne, notContains, notIn, notBetween - mean no item matches, so ne 'gold' keeps a row with no gold in it,
an empty list included. That is why the filter row's ordinary box and a set-filter tick just work
on a list column. Text items follow the grid's text rules (case-insensitive unless
caseSensitive).
| Operator | Operand | A row matches when |
|---|---|---|
hasAny | an array of items | the list holds at least one of them |
hasAll | an array of items | the list holds every one of them (an empty array matches every row) |
hasNone | an array of items | the list holds none of them, an empty list included |
listCount | { op: 'gt' | 'gte' | 'lt' | 'lte' | 'eq', value } | the number of items compares as op says; an empty cell has none |
blank / notBlank | none | the list is empty (or absent) / holds at least one item |
The four list questions compare items exactly, case included, as SQL's
list_has_any does. They are declared through DataType.operators, so a
list column refuses an operator its item type does not offer, and every other column refuses
these, with a [lattice] warning, from filters.set() and
state.apply(). The column's filter panel offers the item type's operators, then
Has any of, Has all of, Has none of and three item counts. The set
filter and the facets tally each item on its own, and a chosen facet value filters with
hasAny.
Sorting orders by the number of items, then by the first item under the item
type's comparator; an empty cell sorts with the other empty cells. Grouping by
a list column groups by the joined text, so gold, silver is one group; grouping by
each item on its own is not offered. Excel receives the joined text in a text
cell: Excel's own format for several values in one cell is not published, and will be written
when it is. The AI schema describes the column as a list of its item type, with
the operators above.
Pushed down. Over a DuckDB LIST column the same questions become
the engine's list functions; see list pushdown.
A list column, executed
A list of tags and a list of sizes, filtered one item at a time and as whole lists, sorted, and exported with the column's joiner. Run headless on every build.
const { createHeadlessGrid } = await import('../packages/core/src/index.js');
// Importing the module registers the type; listModule is the module object.
const { listModule } = await import('../packages/modules/list/index.js');
const grid = createHeadlessGrid({
rowKey: 'id',
columns: [
{ field: 'id', type: 'number' },
{ field: 'tags', type: 'list' },
{ field: 'sizes', type: 'list', typeOptions: { of: 'number', joiner: '; ' } },
],
rows: [
{ id: 1, tags: ['gold', 'silver'], sizes: [8, 10, 12] },
{ id: 2, tags: ['bronze'], sizes: [6] },
{ id: 3, tags: [], sizes: [14, 16] },
],
});
const ids = () => Array.from({ length: grid.rows.count() }, (_, i) => grid.rows.get(i).key).join(',');
grid.filters.set({ col: 'tags', op: 'eq', value: 'gold' }); // any item is gold
const gold = ids();
grid.filters.set({ col: 'sizes', op: 'gt', value: 12 }); // any size above 12
const big = ids();
grid.filters.set({ col: 'tags', op: 'ne', value: 'gold' }); // no item is gold
const notGold = ids();
grid.filters.set({ col: 'tags', op: 'hasAny', value: ['bronze', 'silver'] });
const either = ids();
grid.filters.set({ col: 'sizes', op: 'listCount', value: { op: 'gte', value: 2 } });
const several = ids();
grid.filters.clear();
grid.sort.set([{ col: 'sizes', dir: 'asc' }]); // by count, then first item
const bySize = ids();
const csv = grid.export.csv().split('\r\n').find((line) => line.startsWith('3,'));
grid.destroy();
return `${listModule.name} | ${gold} | ${big} | ${notGold} | ${either} | ${several} | ${bySize} | ${csv}`;