fix(dataeditor): apply default column type and id to reactive columns
Summary
DataEditor.create only applies the documented default column type ("str") to literal column lists. Columns passed as a reactive state Var skip that branch and reach Glide DataEditor without a type, producing an invalid TextCell and crashing at render. Untyped reactive columns also reach Glide without an id, so dict-row data hits the same crash.
This applies the defaults at render time for reactive columns: the columns expression is wrapped so each entry is spread over { type: "str", id: (col.title ?? "").toLowerCase() }, so an explicit per-column type or id still wins (same semantics as the literal path via format_data_editor_column). The wrap uses Var._replace, which preserves the original var's _var_data, so state subscriptions and imports are unchanged.
Alternative considered: patching the default branch of formatCell in .templates/web/utils/helpers/dataeditor.js. That would only stop the TextCell crash at render; the python-side wrap normalizes the column definition itself, which keeps the default co-located with the literal path and also fixes dict-row lookup (id). Note the wrap produces a fresh columns array identity on each render (.map over the reactive value); Glide already re-renders on reactive prop changes, so no memoization contract changes.
Fixes #7596
Type of change
- Bug fix (non-breaking change which fixes an issue)
Testing
test_dataeditor_reactive_columns_default_type: reactiveVarcolumns render as(state.columns).map((col) => ({ type: "str", id: (col.title ?? "").toLowerCase(), ...col }))(columns prop looked up by name).test_dataeditor_reactive_columns_preserve_var_data:rx.State-backed test pinning that the wrap preserves_var_data(state dependency tracked).test_dataeditor_reactive_columns_default_id_supports_dict_rows: dict-row data renders without crashing.test_dataeditor_reactive_columns_js_semantics: node-checked JS semantics - default applies, explicittype/idoverride wins.test_dataeditor_literal_columns_default_type: pins existing literal-path behavior.- New tests fail without the fix;
pytest tests/units/components/datadisplay/test_dataeditor.py: 8 passed.pyright: 0 errors.ruff check/ruff format --check: clean. - Full
pytest tests/units: 12746 passed; 249 failures are all inreflex_cli/v2(deploy/auth/gcp cloud tests needing credentials/network) plus one tty frontend test, none import or touch dataeditor.
cc @masenf