Skip to content

Decision Log: Rich Cell Data Types

Tracks design decisions for Rich Cell Data Types: how reusable rich cells (tokens, composite objects) are packaged for AG Grid so that copy/paste, bulk paste, fill-down, filtering, and export behave consistently. Round 1 records the decisions embedded in the design draft; Round 2 records the questions raised in the PR #99 review.

#QuestionStatusDecisionRound
DQ-001Mechanism for reusable rich cellsDecidedcellDataType + dataTypeDefinitions registryR1
DQ-002Where the value↔string contract livesDecidedIn the data type (valueFormatter + valueParser)R1
DQ-003How renderer + editor attach to a data typeDecidedNamed columnTypes bundle referenced by the data typeR1
DQ-004Single-select vs multi-select tokensDecidedOne tokens family; arity via multiple flagR1
DQ-005Composite columns (Address)Decidedobject data type + popup composite editorR1
DQ-006Bulk paste / fill / export wiringDecidedData-type defaults; per-grid override only for feedbackR1
DQ-007Do image thumbnail + editor use this architecture?DecidedYes — same recipe, later slice (see roadmap list)R2
DQ-008Joint editing of units (quantity + unit of measure)DecidedComposite editor; data type or ColDef factory by storageR2
DQ-009Prioritized list of pre-defined data typesDecidedAdded to the design (§ Pre-defined data type roadmap)R2

Context: The vendor grid’s Role and Order Method columns are hand-rolled inline cellRenderer functions. Renderers are cosmetic only — sorting, filtering, clipboard, fill, and export run against the underlying value — so each hand-rolled column silently breaks copy/paste, set-filtering, and export. We need one unit of reuse that carries the functional hooks, not just the visual ones.

OptionDescriptionTrade-offs
APer-column cellRenderer/cellEditor (status quo)No new machinery, but every column must hand-wire valueFormatter/valueParser/keyCreator or silently break; this is the current drift
BPartial-ColDef factory (createTokenColumn(...)) returning a ColDef fragmentBundles renderer + editor + hooks, but the round-trip wiring is re-applied per factory; nothing forces the next engineer’s createColorColumn onto the same contract
CcellDataType + dataTypeDefinitions registryFormatter, parser, keyCreator, renderer, and editor registered once and applied by name; every column with cellDataType: 'x' inherits the entire round trip identically

Recommendation: Option C — the Phase 2 goal is that copy/paste, bulk paste, and bulk edits behave the same across every rich type; only the data-type registry makes the value↔string round trip the unit of reuse. A thin factory (createTokenDataType) is kept as sugar on top.

Decision: Option C, with Option B retained only as sugar that produces data-type definitions rather than loose ColDefs.

Applied to:

  • Design § The decision and why, § Architecture

DQ-002: Where the value↔string contract lives

Section titled “DQ-002: Where the value↔string contract lives”

Context: Copy, cut, paste, bulk paste, fill-down, and CSV/Excel export are all driven by a string↔value conversion. If that conversion is defined per column (or per grid), rich columns drift apart again.

OptionDescriptionTrade-offs
APer-column valueFormatter/valueParser on each ColDefMaximum flexibility, but N copies of the same contract; inconsistency is the failure mode this project exists to fix
BGrid-level processCellForClipboard/processCellFromClipboard hooksOne place per grid, but export and fill do not run through the clipboard hooks — coverage is partial and grid-specific
CIn the data type: valueFormatter (value→string) + valueParser (string→value)AG Grid consults these for clipboard, fill, and export (useValueFormatterForExport / useValueParserForImport default to true); defined once per type

Recommendation: Option C — it is the only placement that all consuming features (clipboard, fill, export) resolve automatically.

Decision: Option C.

Applied to:

  • Design § Background, § Worked example 1

DQ-003: How renderer + editor attach to a data type

Section titled “DQ-003: How renderer + editor attach to a data type”

Context: DataTypeDefinition carries the value hooks but the visual pair (cellRenderer, cellEditor) and keyCreator attach through column configuration. The binding must be by name so consumers write only cellDataType: 'roles'.

OptionDescriptionTrade-offs
ARepeat cellRenderer/cellEditor on every column defSimple but reintroduces per-column drift for the visual half
BA named columnTypes bundle that the data type references via its columnTypes fieldSingle registration; the grid resolves renderer, editor, and keyCreator from the type name; matches AG Grid’s own extension mechanism

Recommendation: Option B — it completes the “one name, whole behavior” contract.

Decision: Option B.

Applied to:

  • Design § Worked example 1 (registration)

DQ-004: Single-select vs multi-select tokens

Section titled “DQ-004: Single-select vs multi-select tokens”

Context: Role is string[] (multi), Order Method is string (single). They could be two unrelated types or one family.

OptionDescriptionTrade-offs
ATwo independent data types with separate renderers and parsersDuplicated pill rendering and parsing; the two drift visually and behaviorally
BOne tokens family: multiple: truestring[] + multi-select editor; multiple: falsestring + typeahead editor; same TokenList rendererOne factory called twice; only editor selection and parser arity differ

Recommendation: Option B — the consistency payoff is the point of the design.

Decision: Option B.

Applied to:

  • Design § Worked examples 1 and 2

Context: Structured data such as an address must render as one line, edit as several inputs, and still round-trip through copy/paste/fill/export. The same shape recurs for other composites — e.g. joint editing of a quantity with its unit of measure (see DQ-008).

OptionDescriptionTrade-offs
ASplit into sibling scalar columns (street, city, …)Native behavior per column, but no joint editing, wide grids, and cross-field validation is impossible
BHand-rolled popup editor per gridWorks once; re-introduces the per-grid drift for every composite
CAn object data type: single-line valueFormatter, structured valueParser, popup composite editor (cellEditorPopup: true)Same architecture as tokens; all round-trip features free. Requires the row to store the composite as one field

Recommendation: Option C when the row stores one composite field. When the data lives as several sibling row fields, a DataTypeDefinition cannot express the gather/scatter (it has no valueGetter/valueSetter) — that variant is a ColDef factory owning valueGetter/valueSetter, as implemented by combined-column.tsx in ux-prototype. The value contract (formatter/parser/keyCreator/renderer/editor) is shared between the two.

Decision: Option C, with the sibling-fields caveat recorded in the design’s “One field, not many” callout.

Applied to:


Context: Should grids customize clipboard processing, or should the data type’s round trip be the default with validation feedback layered on top?

OptionDescriptionTrade-offs
APer-grid processCell*FromClipboard everywhereFull control, but every grid re-implements the round trip and they drift
BRely on the data type’s formatter/parser; add a generic grid-level processCellFromClipboard only where the Phase 2 invalid-input feedback (red flash + alert) is wantedDefault behavior is automatic and consistent; the override is one generic function consulting the column’s data type, not per-column code

Recommendation: Option B.

Decision: Option B.

Applied to:

  • Design § DataGrid integration, § Validation feedback on paste

DQ-007: Do the image thumbnail and editor use this architecture?

Section titled “DQ-007: Do the image thumbnail and editor use this architecture?”

Context: Raised in review — the grid has an existing hand-rolled image column (grid-image.tsx) with a thumbnail renderer and upload/preview editor, carrying the same copy/filter/export gap as the hand-rolled token columns.

OptionDescriptionTrade-offs
AKeep grid-image.tsx as a one-offNo migration cost now; the gap and the drift remain
BMigrate image to an image cell data type (thumbnail renderer + upload editor; value↔string round trip on the image URL/asset id) in a later sliceSame recipe as tokens/address; consistent behavior; deferred so the first slice stays small

Recommendation: Option B — in scope for the architecture, out of scope for the first slice; sequenced in the pre-defined data type roadmap.

Decision: Option B.

Applied to:

  • Design § Overview, § Pre-defined data type roadmap, § Out of Scope

DQ-008: Joint editing of units (quantity + unit of measure)

Section titled “DQ-008: Joint editing of units (quantity + unit of measure)”

Context: Raised in review — will this help with joint editing of units, similar to the address structured editor?

OptionDescriptionTrade-offs
AComposite object data type (like Address) when the row stores { amount, unit } as one fieldFull round trip for free; joint popup editor with cross-field validation (unit constrains precision, etc.)
BColDef factory with valueGetter/valueSetter (the combined-column.tsx mechanism) when quantity and unit live as sibling row fieldsSame editor and value contract; the gather/scatter must live in the ColDef because data types have no getter/setter

Recommendation: Yes on joint editing in both cases; A vs B is dictated by how the row stores the data, not by the editor. The composite editor and the formatter/parser/keyCreator half are shared.

Decision: Both, selected by storage shape, per the design’s “One field, not many” callout — now explicitly naming units as an example.

Applied to:

  • Design § Bonus — Address (“One field, not many” callout)

DQ-009: Prioritized list of pre-defined data types

Section titled “DQ-009: Prioritized list of pre-defined data types”

Context: Raised in review — the ux-prototype library should publish a prioritized, aspirational list of pre-defined data types that it will ship as they are needed and mature (e.g. Text, Number (Decimal), Boolean, …).

OptionDescriptionTrade-offs
ALeave the type inventory implicit in each design’s scope sectionNo single place to see what exists vs. what is planned
BAdd a prioritized roadmap section to the design listing built-in types to adopt and custom types to build, in shipping orderOne authoritative list; each future slice picks the next entry

Recommendation: Option B.

Decision: Option B — see the design’s new § Pre-defined data type roadmap.

Applied to:

  • Design § Pre-defined data type roadmap

Copyright: (c) Arda Systems 2025-2026, All rights reserved