Skip to content

fix: scope repeating group validation errors to the invalid instance (#1985)#1999

Open
clinnygee wants to merge 1 commit into
mainfrom
issue/1985
Open

fix: scope repeating group validation errors to the invalid instance (#1985)#1999
clinnygee wants to merge 1 commit into
mainfrom
issue/1985

Conversation

@clinnygee

Copy link
Copy Markdown
Collaborator

Fixes #1985

Problem

Validation errors on repeating group items showed on all instances when only one was invalid. Errors were stored/looked up in a flat Record<linkId, OperationOutcome>, and every field looked itself up as invalidItems[qItem.linkId]. Because all instances of a repeat-group child share one linkId, they collided on a single key — one invalid instance lit up all of them. The save gate was unaffected; this was purely a display issue.

Fix

Errors are now keyed by linkId plus the path of enclosing repeat-group instance indices (e.g. child-field///1). Non-repeating items have an empty path, so their key stays a bare linkId — no behaviour change.

Validation (a pure function over the QR) and the display hook build the identical key from one shared helper, so they always agree without mutating or persisting anything into the QuestionnaireResponse. The instance-index path reaches descendants through a small React context provided per repeat instance / gtable row.

  • New utils/validateErrorKey.tsgetValidationErrorKey() / getBaseLinkIdFromErrorKey()
  • New contexts/RepeatGroupInstanceContext.ts — carries the instance-index path
  • utils/validate.ts — threads repeatInstancePath through the recursion and keys all three error write sites via the helper
  • RepeatGroupItem.tsx and GroupTableRow.tsx — provide their index path via the context
  • useValidationFeedback.ts — reads the context and looks up the instance-scoped key (no signature change, so the ~25 leaf components are untouched)
  • SaveAsFinalAction.tsx — maps error keys back to base linkIds so "jump to first error tab" still resolves

Why not the literal qrItem.id ?? linkId from the issue?

The primary reported case is an empty required field, which has no qrItem at the leaf (it arrives as undefined) — so there'd be nothing to carry an id. A position-path key handles that case, needs no QR mutation/stripping, and composes for nested repeat groups.

Out of scope (follow-ups)

  • targetConstraint per-instance validation (explicitly deferred in the issue)
  • Repeating single (non-group) items — still keyed by linkId

Nested repeat groups and gtable rows are covered by this change.

Testing

  • New test/validateErrorKey.test.ts (pure helper) and test/validateRepeatInstance.test.ts (end-to-end validateForm: only the empty instance is flagged, not the answered one nor the bare linkId)
  • Full renderer suite: 2179 passed
  • Renderer npm run build: clean · npm run lint: 0 errors · app tsc --noEmit: clean

🤖 Generated with Claude Code

…1985)

Validation errors were stored/looked up in a flat map keyed only by `linkId`,
so all instances of a repeating group child shared one key. A single invalid
instance therefore displayed its error on every instance.

Errors are now keyed by `linkId` plus the path of enclosing repeat-group
instance indices (e.g. `child-field///1`). Non-repeating items keep a bare
`linkId` key, so their behaviour is unchanged. Validation and the display hook
build the identical key from a shared helper (getValidationErrorKey), and the
instance-index path is supplied to descendants via a React context
(RepeatGroupInstanceContext) provided per RepeatGroup instance and gtable row.
This works even when a required field has no qrItem yet, and requires no
mutation of the QuestionnaireResponse.

- add utils/validateErrorKey.ts (getValidationErrorKey / getBaseLinkIdFromErrorKey)
- add contexts/RepeatGroupInstanceContext.ts
- thread repeatInstancePath through validate.ts and key all error write sites
- provide the context in RepeatGroupItem and GroupTableRow
- consume the context in useValidationFeedback
- export the helpers; map error keys back to base linkIds in SaveAsFinalAction
  so "jump to first error tab" still resolves
- add unit + integration tests

Out of scope (follow-ups): targetConstraint per-instance validation and
repeating single (non-group) items remain keyed by linkId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Validation errors on repeating group items show on all instances when only one is invalid

1 participant