Skip to content

fix(StructuredSelector): seed declared defaults for accessor-chain bindings - #1339

Merged
nebojsa-peric merged 2 commits into
masterfrom
fix/master/accessor-chain-default-seeding
Oct 7, 2026
Merged

nebojsa-peric merged 2 commits into
masterfrom
fix/master/accessor-chain-default-seeding

Conversation

@nebojsa-peric

Copy link
Copy Markdown
Collaborator

Fixes #1337.

A {bind} object writes the prop's declared default to the store when the widget initializes. Accessor chains wrote nothing, so the result depended on how the binding was written:

  • a chain-bound field held undefined instead of its emptyValue (null)
  • a chain-bound LineGraph (or another chart element with active) was not drawn until toggled
  • a chain-bound Slider positioned its handle at NaN% and wrote NaN to the store on mouse wheel

#1336 and #1338 added specs and a litmus page that reproduce this.

Fix

StructuredSelector.getSelectorConfig now collects the declared default for accessor chains, the same way it does for binding objects (2 lines). Existing store values are never overwritten. The v != pv guard keeps a chain nested inside a structured prop (style={{ color: m.x }}, where props and values are the same object) from writing the chain function itself as its default.

Tests

With the fix applied, the four accessor-chain cases from #1338 failed, because the store now held the default. They now assert the intended behavior:

  • LineGraph: a chain-bound series stores active = true and draws its line. A stored false is kept for both binding styles.
  • Slider: a chain-bound slider stores 0 with its handle at 0%, the mouse wheel steps it to 1, and an existing value is kept.
  • Field: a chain-bound field stores null (or a custom emptyValue), and existing values are not overwritten.
  • StructuredSelector: both binding styles collect defaults the same way, an explicit defaultValue on the binding wins over the declared one, and chains nested in structured props get none.

558 passing, check-types clean. The text on the litmus page bugs/FieldBindingObjectNullSeeding now describes the fixed behavior. In the browser, both columns now match for all three widgets.

Behavior change

This changes what apps that use accessor chains find in the store, so it ships as 26.10.0 with an entry in breaking-changes.mdx. The entry lists every affected widget and prop, and what to check when upgrading:

  • === undefined comparisons and "key" in data checks
  • null keys that now appear in JSON sent to a server
  • $record editors inside a Grid or Repeater, which now write the default into each record they render

Commits

  1. fix(StructuredSelector): …: the fix, specs, litmus page, breaking-changes entry
  2. Bump cx version to 26.10.0: package.json and changelog

🤖 Generated with Claude Code

…ndings (#1337)

A {bind} object writes the prop's declared default (Field emptyValue,
LineGraph active, Slider to, ...) to the store when the widget
initializes. Accessor chains wrote nothing, so a chain-bound field held
undefined instead of null, a chain-bound LineGraph was not drawn, and a
chain-bound Slider positioned its handle at NaN% and wrote NaN on mouse
wheel. Chains now collect the declared default like binding objects do.
Existing store values are never overwritten, and chains nested inside
structured props get no default.
@nebojsa-peric
nebojsa-peric merged commit 282fec7 into master Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Field store initialization depends on binding style: {bind} seeds emptyValue (null), accessor chains leave undefined

1 participant