Columns from Data
Bind rows and no columns, and the grid derives them from the data's shape — typed, humanized, and still ordinary column definitions you can override one at a time.
No column definitions at all
This grid binds a data source and a config, and nothing else. Sort Weight Kg and the numbers order numerically; sort Dispatched and the rows order by date.
Six columns, none of them written
The grid above is <gridcraft [dataSource]="dataSource" [config]="config" /> —
there is no [columns] binding on it. Every header, every alignment and every filter
came from the rows.
They are typed, not just present
Sort Weight Kg: the order is 2, 4, 8, 17… not 1200, 17, 2. Sort Dispatched: the rows order by date, not by the text of a weekday name. Open the filter under Delivered: it is a Yes / No dropdown. A generated column goes through the same type engine a hand-written one does — see Cell Data Types.
Headers are read from the key
customerRef becomes Customer Ref and id becomes
ID. It is a default label, not a translation — write
headerFrom for your own wording, or a column's name for one header.
The courier column is missing, and that is deliberate
courier holds an object. Generation skips it rather than printing
[object Object]. The next example brings it back in one line.
Two columns written, the rest generated
Courier reaches a nested value generation skips, and Weight Kg states only a width — it keeps the generated header and numeric type.
Two written columns, four generated
This grid binds [columns] with exactly two entries and sets
autoGenerateColumns: true. The written ones come first, in the order you wrote them;
the rest of the keys follow.
A written column keeps what it did not say
Weight Kg is written as { key: 'weightKg', prop: 'weightKg', width: 120 }
— no name, no type. It renders with the generated header Weight Kg and still sorts
numerically, because a supplied definition merges over the generated one field by field instead of
replacing it.
{ key: 'weightKg', prop: 'weightKg', width: 120 } // name and dataType come from generation
Reaching a nested value
Courier is the key generation skipped. One hand-written column with a dotted
prop renders it, and the other five columns are still generated:
{ key: 'courier.name', name: 'Courier', prop: 'courier.name', filter: {} }
When to use it
Bind a data source, bind no columns, and the grid derives them from the data's shape — one column per scalar key, in the order the keys appear. It is the fastest way to see your data in a grid, and it survives contact with real work: a generated column is an ordinary column definition, so you can keep generation and write the two columns you care about.
How to turn it on
- Bind no
[columns]— generation happens on its own. autoGenerateColumns: true— generate even though[columns]is bound, filling in the keys those columns do not cover.autoGenerateColumns: false— never generate, even with no columns bound. An empty grid on purpose.
What a generated column looks like
keyandprop— the object key.name— a humanized label:firstName→ First Name,api_url→ API URL.dataType— read from the data, so sorting, filtering and cell text all match what the column holds.sortableandresizable.- Never
editable. Editing is something you ask for, not something a grid decides for your data. - No width — the sizing modes decide. See Sizing Modes.
What it skips
- Objects, arrays and functions — a nested value has no obvious cell text, so
the key is left out rather than printed as
[object Object]. Write that column by hand with a dottedprop. - Keys starting with
__— internal fields. - Column groups — nesting cannot be read from a flat object, so generation never invents one. Groups you write yourself pass through untouched. See Column Groups.
It reads the data once
Generation runs when the grid first has rows and then holds still. A row arriving later with a field nobody has seen does not grow the table under the reader — the layout they resized stays the layout they resized. When you do want the new field, ask for it:
grid.regenerateColumns(); // on a ViewChild of the grid component
Discovery reads the first 20 rows by default, so the cost is the same on twelve rows as on a
hundred thousand. A key that appears only after those rows needs a wider
sampleSize — or one hand-written column.
Options
readonly config: GridConfig<Shipment> = {
autoGenerateColumns: {
// Read 50 rows instead of 20 when discovering the keys.
sampleSize: 50,
// Never build a column for these.
exclude: ['id'],
// Your own header text. Return the key itself to leave it raw.
headerFrom: key => key.replace(/([a-z])([A-Z])/g, '$1 $2'),
},
};
Generating the definitions yourself
The same function the grid runs is exported, so you can generate once, adjust the result and pass it in as ordinary column definitions — useful when you want to store the layout, or show the user what was derived:
import { generateColumnDefs } from '@gridcraft/angular';
readonly columns = generateColumnDefs(this.rows).map(c =>
c.key === 'weightKg' ? { ...c, width: 120 } : c);
Column widths, order, pinning and hidden state persist by column key, and a
generated key is the object key — so a saved layout keeps matching across reloads. See
Grid State.
Generation options
| Property | Type | Default | Description |
|---|---|---|---|
| config.autoGenerateColumns | boolean | AutoGenerateColumns | — | Derive column definitions from the data. Omitted, generation happens only when no columns are bound; true generates alongside supplied columns; false never generates. |
| autoGenerateColumns.sampleSize | number | 20 | Rows read to discover the keys. A key that first appears after them does not become a column. |
| autoGenerateColumns.exclude | string[] | [] | Keys that never become columns. |
| autoGenerateColumns.headerFrom | (key: string) => string | humanized | Header text for a key. A column's own name still wins over it. |
| columns | GridColumn[] | ColumnGroup[] | — | Optional. Bind nothing and the columns are generated; bind some and each merges field-by-field over the generated definition for the same key. |
| regenerateColumns() | () => void | — | Re-derive the generated columns from the rows the grid holds now. No-op when generation is off. |
| generateColumnDefs(rows, options?) | (rows, options?) => GridColumn[] | — | The exported function the grid itself runs. Generate the definitions in your own code, adjust them, and pass them in as ordinary columns. |
| humanizeKey(key) | (key: string) => string | — | The default header label, exported so a custom headerFrom can fall back to it. |