feat(formulus-formplayer): Add dynamic choice lists with WHERE clause and age filtering support#277
Conversation
Implements dynamic dropdown population from local observations with:
- Custom DynamicEnumControl renderer for x-dynamicEnum fields
- Template parameter resolution ({{data.field}} syntax)
- WHERE clause filtering with operators (=, !=, <, >, <=, >=, AND, OR)
- Cascading dropdown support with real-time dependency tracking
- Distinct value filtering for unique choices
- FormEvaluationContext for extension function management
Core Components:
- DynamicEnumControl.tsx: React renderer with MUI Autocomplete
- FormEvaluationContext.tsx: React context provider
- builtinExtensions.ts: getDynamicChoiceList function with WHERE clause generation
- FormulusInjectionScript.js: Native bridge with WHERE clause parser
- ExtensionService.ts: Extension loading with ext.json normalization
Replaces ODK-X linked tables and 'select person' functionality.
Features:
- Query any form type (household, hh_person, etc.)
- Filter by parameters or complex WHERE clauses
- Cascading village → subvillage → household → person
- Age-based filtering, sex-based filtering
- Real-time updates when dependency values change
Documentation:
- Comprehensive guide with 8 real-world examples
- Query syntax reference with common patterns
- Troubleshooting guide with debug procedures
- Migration guide from static enums and ODK-X
- Production readiness checklist
Breaking Changes: None - fully backward compatible
Testing: Tested with cascading village/subvillage, multiple filters,
WHERE clauses, and production error handling.
|
the reason you have all these changes is that you rebased wrongly @Mishael-2584. Let me see how I can help. You can look through again to see if all your intended changes are still available |
Hi @Jexsie. Thanks for the assistance.. I have noticed the large diff isn’t actually from the rebase. If you try track down the commits, only 4 files changed. (e568f61)) were from that. I think the main issue comes in from the Prettier commit. My actual feature commit (71edc35) Let us see how we can still solve these conflicts and clean it up. I will set as draft for now |
|
Your prettier changes are against the prettier configuration. You have form player build assets pushed. These are not tracked by git. But yeah, let's have this fixed |
|
Yes precisely this was the issue |
Formplayer assets are built by the formulus-android workflow and provided as artifacts during the APK build. They should not be committed.
This reverts commit 1ea4d81.
This reverts commit ab0fbdc.
…filtering, age_from_dob - Add getObservationsByQuery with whereClause support in FormService - Support data.field and json_extract formats in filterObservationsByWhereClause - builtinExtensions: getDynamicChoiceList with age_from_dob JS filtering - FormulusMessageHandlers: fix payload extraction for getObservationsByQuery - formulus-load.js: polyfill ensures correct message routing to native - Synkronus: app/forms/ bundle structure for AnthroCollect - Log cleanup, documentation updates (DYNAMIC_CHOICE_LISTS.md)
- getObservationsByQuery with whereClause, filterObservationsByWhereClause - builtinExtensions: getDynamicChoiceList, age_from_dob JS filtering - FormulusMessageHandlers: getObservationsByQuery payload handling - formulus-load.js polyfill for correct message routing - WebView assets: FormulusInjectionScript, formulus-api, formulus-load - Synkronus: app/forms/ bundle structure for AnthroCollect - ExtensionService, FormplayerModal, log cleanup - DYNAMIC_CHOICE_LISTS.md documentation
Brings in complete feature from dev: - getObservationsByQuery, filterObservationsByWhereClause - builtinExtensions, FormulusMessageHandlers, formulus-load.js - WebView assets (FormulusInjectionScript, formulus-api, formulus-load) - formplayer_dist formulus-load.js, index.html - ExtensionService, Synkronus app/forms/, documentation
…anner logic - Introduced VisionCameraErrorBoundary to handle errors from the VisionCamera module. - Refactored QRScannerModal to conditionally load QRScannerModalImpl based on the availability of the VisionCamera native module. - Updated gradle.properties to optimize memory settings for lower-end devices, reducing JVM args and worker count for Gradle builds.
|
Thanks @Mishael-2584 |
Description
This PR introduces a comprehensive dynamic choice list feature that enables form fields to populate dropdown options dynamically from the local database at runtime. This eliminates the need for static enum values that can become outdated, allowing forms to always display current data.
Key Features
DynamicEnumControl) that supportsx-dynamicEnumschema extensiongetDynamicChoiceListfunction that queries local observations via the Formulus WebView bridgedata.sex = 'male',age_from_dob(data.dob) >= 18)age_from_dob(data.dob)function that calculates age from date of birthFormEvaluationContext) that provides extension functions to form componentsTechnical Implementation
formulus-formplayer:
DynamicEnumControl.tsx- Custom renderer for dynamic enumsbuiltinExtensions.ts- Built-ingetDynamicChoiceListfunction with age calculation logicFormEvaluationContext.tsx- Context provider for extension functionsApp.tsx- Integrated built-in extensions and removed error message displayExtensionsLoader.ts- Support for built-in extension functionsformulus:
FormplayerModal.tsx- Fixed extension base path to/formsdirectoryExtensionService.ts- Enhanced extension loading logicreact-native.config.js- Added webview assets to React Native configandroid/app/build.gradle- Added JSX and HTML file copying for webview assetsDocumentation:
DYNAMIC_CHOICE_LISTS.md- Comprehensive 780-line reference guide with examplesWhat This Enables
Forms can now:
hh_person,household) for dropdown optionssex: 'male'+age_from_dob(data.dob) >= 18)Example Usage
{ "select_person": { "type": "string", "x-dynamicEnum": { "function": "getDynamicChoiceList", "query": "hh_person", "params": { "whereClause": "age_from_dob(data.dob) >= 18 AND data.sex = 'male'" }, "valueField": "observationId", "labelField": "data.names" } } }Type of Change
Component(s) Affected
Related Issue(s)
Closes/Fixes/Resolves:
Testing
age_from_dob()functionTesting Notes
test_dynamicformBreaking Changes
If breaking changes, please describe migration steps:
N/A - This is a purely additive feature. Existing forms continue to work unchanged. The
x-dynamicEnumextension is optional and only used when specified in the schema.Documentation Updates
Documentation Added
DYNAMIC_CHOICE_LISTS.md: Comprehensive 780-line reference guide including:age_from_dob()functionChecklist
Implementation Details
Files Changed
Core Feature Files:
formulus-formplayer/src/DynamicEnumControl.tsx(359 lines) - Custom rendererformulus-formplayer/src/builtinExtensions.ts(583 lines) - Query function with age logicformulus-formplayer/src/FormEvaluationContext.tsx(74 lines) - Context providerformulus-formplayer/src/App.tsx- Integration and error handling updatesformulus/src/components/FormplayerModal.tsx- Extension path fixformulus/src/services/ExtensionService.ts- Extension loading enhancementsDYNAMIC_CHOICE_LISTS.md(779 lines) - Complete documentation