diff --git a/docs/development/installing-formulus-dev.md b/docs/development/installing-formulus-dev.md index 0d751b2..330f0df 100644 --- a/docs/development/installing-formulus-dev.md +++ b/docs/development/installing-formulus-dev.md @@ -160,18 +160,20 @@ adb install app-debug.apk ```bash -# Download and install in one command -curl -L https://github.com/OpenDataEnsemble/ode/releases/download/v1.1.1/formulus.apk -o /tmp/formulus.apk -adb install /tmp/formulus.apk +# Browse the release and download the arm64-v8a APK for most phones: +# https://github.com/OpenDataEnsemble/ode/releases/tag/v1.2.1 +# Asset names look like: formulus-v1.2.1-25-arm64-v8a-release-YYYYMMDD.apk +adb install /path/to/formulus-v1.2.1-*-arm64-v8a-release-*.apk ``` ```powershell -# Download and install -Invoke-WebRequest -Uri "https://github.com/OpenDataEnsemble/ode/releases/download/v1.1.1/formulus.apk" -OutFile "$env:TEMP\formulus.apk" -adb install "$env:TEMP\formulus.apk" +# Browse the release and download the arm64-v8a APK for most phones: +# https://github.com/OpenDataEnsemble/ode/releases/tag/v1.2.1 +# Asset names look like: formulus-v1.2.1-25-arm64-v8a-release-YYYYMMDD.apk +adb install "C:\path\to\formulus-v1.2.1-*-arm64-v8a-release-*.apk" ``` diff --git a/docs/getting-started/installation/installing-formulus.md b/docs/getting-started/installation/installing-formulus.md index 5253bb9..435ec61 100644 --- a/docs/getting-started/installation/installing-formulus.md +++ b/docs/getting-started/installation/installing-formulus.md @@ -86,7 +86,7 @@ You have two options to install Obtainium: ![Obtainium Add App Screen](/img/installation/obtainium-add-app.png) -**Stable release:** Install **v1.1.1** (or the latest [GitHub release](https://github.com/OpenDataEnsemble/ode/releases)). Pre-release toggles are only needed for alpha/beta testing. +**Stable release:** Install **v1.2.1** (or the latest [GitHub release](https://github.com/OpenDataEnsemble/ode/releases)). Pre-release toggles are only needed for alpha/beta testing. #### Step 3: Install Formulus @@ -97,7 +97,7 @@ You have two options to install Obtainium: - App name: **ode** - Developer: **OpenDataEnsemble** - Package: `org.opendataensemble.formulus` - - Latest version: **v1.1.1** (or current [release](https://github.com/OpenDataEnsemble/ode/releases)) + - Latest version: **v1.2.1** (or current [release](https://github.com/OpenDataEnsemble/ode/releases)) - Status: **Not installed** 5. **Tap the "Install" button** at the bottom of the screen 6. **Confirm installation** when prompted: diff --git a/docs/guides/building-custom-apps-v2.md b/docs/guides/building-custom-apps-v2.md index e43588a..cb9740f 100644 --- a/docs/guides/building-custom-apps-v2.md +++ b/docs/guides/building-custom-apps-v2.md @@ -560,22 +560,25 @@ Upload to Synkronus: ## How it works: Data injection -When you call: +Prefer `defaultData` (keys must match schema root properties): ```javascript await api.openFormplayer( 'pull_shot', - { bean: beanName }, // Inject this value + { defaultData: { bean: beanName } }, {} ) ``` +Legacy flat keys on the params object (other than reserved bridge keys) are still accepted when `defaultData` is omitted. + The Formulus API: 1. Opens the `pull_shot` form -2. Pre-fills the `bean` field with the provided value -3. Marks it read-only (from ui.json) -4. User fills in the rest (yield, time, rating) -5. When submitted, the observation includes the injected value +2. Prefills matching schema fields from `defaultData` +3. User fills in the rest (yield, time, rating) +4. When submitted, the observation includes the injected value + +**Important — visibility vs injection:** Formplayer **clears** a field when its Control is hidden by a `SHOW`/`HIDE` rule. Injected stamps must live in the **schema** (and `defaultData`) and must **not** be bound to a Control that starts hidden. To show the value read-only, use SwipeLayout `headerFields` or a separate computed / `lbl_*` display field—not a hidden Control on the real property. See [Form design — Conditional Logic](./form-design.md#conditional-logic-in-ode-forms). --- diff --git a/docs/guides/form-design.md b/docs/guides/form-design.md index 5a32a71..4e77bd2 100644 --- a/docs/guides/form-design.md +++ b/docs/guides/form-design.md @@ -891,6 +891,21 @@ Rules are defined in the UI schema using the `rule` property on Control elements } ``` +:::warning Clear-on-hide deletes the field value +When Formplayer hides a **Control** (`SHOW` until the condition is true, or `HIDE` when the condition is true), it **clears that field’s value** from the observation (ODK-style `relevant` behaviour). This is intentional for user-entered answers that should not stay when the question is no longer relevant. + +**Do not** put `SHOW`/`HIDE` on fields you need to keep—especially values injected by a custom app via `defaultData` (cluster IDs, device role, AF codes, enrollment mode, etc.). + +**Recommended pattern for injected / stamp fields:** + +1. Declare the field in `schema.json` so it can be stored and validated. +2. Pass it in `openFormplayer` / `FormInitData` as `params.defaultData`. +3. **Do not** add a UI `Control` for that field (or never attach a visibility rule to it). +4. If the enumerator must **see** the value, use a separate display-only / computed proxy (for example `lbl_region`, `lbl_af`) or list the stamp in SwipeLayout `headerFields`—not a hidden Control on the real field. + +Using a Control solely to “hide” an injected field will wipe the inject on open and can cause required-field failures or silent data loss. +::: + ### Scope Resolution Rules **Critical Rule**: Rule condition scopes **must exist in the schema at all times**, even when the field is hidden. The scope is evaluated against the current form data. diff --git a/docs/reference/formplayer-contract.md b/docs/reference/formplayer-contract.md index 92e9f28..d5bdaa6 100644 --- a/docs/reference/formplayer-contract.md +++ b/docs/reference/formplayer-contract.md @@ -738,6 +738,8 @@ Use `type: object` with `format: select_file`. The Formplayer stores **basename- | `ENABLE` | Element is disabled until condition is true | | `DISABLE` | Element is enabled until condition is true | +> **Clear-on-hide:** For `SHOW` and `HIDE`, when a Control becomes not visible Formplayer **deletes that field’s value** from form data (see `useClearOnHide`). Use visibility rules only for answers that should reset when irrelevant. Keep injected / stamp fields in the schema and `defaultData` **without** a hidden Control—display via `headerFields` or a separate computed/`lbl_*` field if needed. Details: [Form design — Conditional Logic](../guides/form-design.md#conditional-logic-in-ode-forms). + ### Condition Schema **Supported Condition Types:**