Skip to content

fix: Linked table nested form lifecycle - preserve parent form state across child form sessions#591

Merged
IamLRBA merged 9 commits intoOpenDataEnsemble:devfrom
najuna-brian:linked-table-support
Apr 14, 2026
Merged

fix: Linked table nested form lifecycle - preserve parent form state across child form sessions#591
IamLRBA merged 9 commits intoOpenDataEnsemble:devfrom
najuna-brian:linked-table-support

Conversation

@najuna-brian
Copy link
Copy Markdown
Contributor

Description

Summary

Linked-table question types in AnthroCollect need to open a child form on top of a parent form, wait for the child to be completed or dismissed, and then return to the parent form exactly where it was — same page, same field state, same scroll position. This matches the behavior that existed in the original OMO repo running on top of ODK-X.

This PR fixes the root cause: the native Formulus app was destroying the parent form modal before opening the child form, making state restoration impossible.

image

Problem

The original App.tsx maintained a single formplayer modal instance. When openFormplayer was called while a modal was already visible, it explicitly closed the existing modal first:

// Old code — parent is torn down before child opens
if (formplayerVisibleRef.current) {
  setFormplayerVisible(false);
  await new Promise<void>(resolve => setTimeout(() => resolve(), 300));
}

This meant:

  • The parent form's React state was unmounted and lost
  • The parent's current page position was lost
  • The parent's WebView was destroyed and would have to reinitialise from scratch
  • Returning to the parent after the child completed required the parent to reload entirely

Solution

Replace the single-modal design with a modal stack. Each openFormplayer call pushes a new entry onto the stack. The parent modal stays mounted underneath the child modal. When the child closes, the parent becomes the top of the stack again and receives a focus notification so the form JS layer can react.

Key concepts

Concept Detail
formplayerStack Array of FormplayerStackEntry objects, one per open form level
isActive prop Only the top-of-stack modal is isActive=true; all others are false
Submission guard Submission handler only registers when visible && isActive - inactive parent modals don't compete
State preservation Form state reset only fires when visible goes false, not when isActive changes
Focus handoff When isActive transitions false → true on a ready WebView, onReceiveFocus() is injected into the WebView JS context
Retry initialiser initializeStackEntry polls for the modal ref up to 20 times × 100ms to handle slow mounts before calling initializeForm

@najuna-brian najuna-brian requested a review from r0ssing April 8, 2026 14:39
@najuna-brian najuna-brian force-pushed the linked-table-support branch from cd56b53 to 8804710 Compare April 11, 2026 12:36
@najuna-brian najuna-brian marked this pull request as draft April 11, 2026 16:28
@najuna-brian najuna-brian force-pushed the linked-table-support branch from fffb1d6 to db15d86 Compare April 11, 2026 20:07
@najuna-brian najuna-brian marked this pull request as ready for review April 11, 2026 23:15
Comment thread formulus/src/components/FormplayerModal.tsx
Copy link
Copy Markdown
Contributor

@r0ssing r0ssing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename to sub-observation as agreed

Comment thread formulus/src/components/FormplayerModal.tsx
Comment thread formulus/src/components/FormplayerModal.tsx
Comment thread formulus-formplayer/src/App.tsx
@IamLRBA IamLRBA requested a review from r0ssing April 14, 2026 20:29
@najuna-brian
Copy link
Copy Markdown
Contributor Author

Let's rename to sub-observation as agreed

Thanks @r0ssing,
This will be addressed in a follow-up PR as agreed.

@IamLRBA IamLRBA merged commit 3d3ed6c into OpenDataEnsemble:dev Apr 14, 2026
10 checks passed
@najuna-brian najuna-brian deleted the linked-table-support branch April 14, 2026 20:37
@najuna-brian najuna-brian restored the linked-table-support branch April 14, 2026 21:12
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.

5 participants