Skip to content

No public API to read fetched rows through entity accessors, so computed columns cannot be exported #128

Description

@matej21

Summary

fetchAllData (and useDataViewFetchAllData) returns the unpaged rows as raw records. A column whose cell is computed reads its row through an EntityAccessor (ColumnLeafProps.renderCell(accessor)), so an export has no way to evaluate that column for the fetched rows. The built-in DataViewExportTrigger drops such columns (c.fieldName !== null), and a custom export has to rebuild bindx internals to get an accessor per row.

Environment

  • @contember/bindx@0.1.52 / @contember/bindx-dataview@0.1.52
  • contember/bindx@main as of 78c1712

What an application does today

An application exporting a DataGrid to a spreadsheet needs the same text for a computed column that the cell shows (a composed label, a count, a derived status). To read a fetched row through accessors it constructs a private store per export:

import { ActionDispatcher, EntityHandle, SnapshotStore, setEntityData } from '@contember/bindx'

const store = new SnapshotStore()
const dispatcher = new ActionDispatcher(store)
const readRow = (data: Record<string, unknown>): EntityAccessor<object> => {
	const id = data['id'] as string
	dispatcher.dispatch(setEntityData(entityType, id, data, true))
	return EntityHandle.create(id, entityType, store, dispatcher, schema, undefined, selectionMeta)
}

It must not load the rows into the page's store: that would keep every exported row in memory and mix them into the entities the page edits.

This works, but it couples the application to the store, the dispatcher, the action creators and the positional EntityHandle.create signature (the undefined is the brands slot) — all of which can change in any release.

Expected behavior

A supported way to read rows that were fetched outside the store through read-only accessors, isolated from the page store, so computed columns can be exported.

Proposal

Two layers; the first is enough on its own.

  1. @contember/bindx: a detached reader.

    interface DetachedEntityReader {
    	/** Wraps one fetched record. The accessor reads only what `selection` covers. */
    	read(data: Record<string, unknown>): EntityAccessor<object>
    }
    function createDetachedEntityReader(options: {
    	schema: SchemaRegistry
    	entityType: string
    	selection: SelectionMeta
    }): DetachedEntityReader

    It owns its own store and dispatcher; dropping the reader releases everything it loaded. Writes through its accessors should either be rejected or stay local — a maintainer call.

  2. @contember/bindx-dataview: let an export factory evaluate a column for a row, e.g. ExportFactoryArgs.rows: readonly { data: Record<string, unknown>; accessor(): EntityAccessor<object> }[] (lazy, so a plain field export pays nothing), built on the reader from (1).

Open design questions for the maintainers: the name and home of the reader; whether its accessors are read-only; whether DataViewExportTrigger should start exporting computed columns (it would need a text form of a cell — see #126 for a per-column slot that could carry it).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions