# QuestionnaireResponseForm

Canonical page: https://docs.ovok.com/native-sdk/guide/components/questionnaire-response-form

`QuestionnaireForm` renders a FHIR `Questionnaire` as a compound component. It supports paged or all-items layouts, enabled-when conditions, default answers, required-field validation, and either caller-owned submission or the SDK's FHIR `QuestionnaireResponse` creation.

```tsx
<QuestionnaireForm
  questionnaire={questionnaire}
  onSubmit={async (values) => saveValues(values)}
>
  <QuestionnaireForm.Header>
    <QuestionnaireForm.Header.Title />
    <QuestionnaireForm.Header.Subtitle />
  </QuestionnaireForm.Header>
  <QuestionnaireForm.Content>
    <QuestionnaireForm.Content.Item />
    <QuestionnaireForm.Content.Error />
  </QuestionnaireForm.Content>
  <QuestionnaireForm.Navigation>
    <QuestionnaireForm.Navigation.PreviousButton />
    <QuestionnaireForm.Navigation.NextButton />
    <QuestionnaireForm.Navigation.SubmitButton />
  </QuestionnaireForm.Navigation>
</QuestionnaireForm>
```

## Props and submission modes [#props-and-submission-modes]

`questionnaire` is required. `paged` defaults to `true`; when false, the root is a `ScrollView` and `Content.AllItems` is the matching content primitive. The root also accepts the relevant React Native `ViewProps`/`ScrollViewProps`, `style`, and `testID`.

The module also exposes providers, hooks, contexts, and a response builder for custom
renderers. See [advanced API](/native-sdk/guide/components/questionnaire-response-form/advanced-api/).

Choose exactly one submission mode:

- `onSubmit(values, formikHelpers?)`: the app owns persistence. The callback is async and receives `QuestionnaireFormValues`; the SDK does not create a FHIR response in this mode.
- `onSuccess(response)` and optional `onError(error)`: the SDK gets the active profile from `@ovok/core`, builds a completed `QuestionnaireResponse`, adds `subject` and a stable identifier, and calls `createResourceIfNoneExist`. This mode requires a configured core client/profile.

The SDK-managed mode assigns a stable identifier and uses `createResourceIfNoneExist`.
The identifier is retained for the form instance, so a second legitimate submission
of the same questionnaire can be treated as an existing response. Remount the form or
use the app-owned `onSubmit` mode when repeated submissions are separate records.

When observation extraction is enabled, the SDK saves extracted resources and the
completed `QuestionnaireResponse` in one FHIR transaction. After the transaction
succeeds, it invalidates cached searches for the response and each extracted
resource type before returning the reloaded response. A rejected transaction does
not invalidate caches or report submission success.

`initialValues` can seed answers. Values are strings, booleans, `null`, or `undefined`; the SDK removes disabled conditional answers during validation.

Importing `@ovok/native/questionnaire-response-form` registers English defaults for the form's buttons, yes/no choices, progress subtitle, validation and submission errors, and accessibility hints. Existing English resources are not overwritten, so an app can provide its own copy. Decimal text questions accept either `.` or `,` as the decimal separator; the form normalizes the value before creating the FHIR `valueDecimal`.

## FHIR and UI behavior [#fhir-and-ui-behavior]

Top-level groups become pages. If the questionnaire has no group items, the SDK creates one synthetic page. In paged mode, one enabled item is shown at a time. In all-items mode, `Content.AllItems` renders the enabled items in a flat list.

Supported item renderers and response mapping are defined by the current source; common types include `boolean`, `choice`, `date`, `dateTime`, `decimal`, `integer`, `string`, and `text`. Conditional items use `enableWhen` with `all` or `any` behavior. `answerOption.initialSelected` seeds choices when an item becomes active.

Required validation runs before submission and considers only enabled items. Paged navigation also prevents advancing from an unanswered required item.

## Compound exports [#compound-exports]

`Header`, `Header.Title`, `Header.Subtitle`, `Content`, `Content.Item`, `Content.AllItems`, `Content.Error`, `Navigation`, `Navigation.PreviousButton`, `Navigation.NextButton`, and `Navigation.SubmitButton` are exported from the compound root. The form provider and hooks are public for custom layouts; use them only inside the corresponding form context.

`useQuestionnaireForm()` returns the Formik state plus questionnaire navigation data,
`errorMessage`, `submissionError`, and `retrySubmit()`. Validation errors clear once
the enabled items are valid. `submissionError` takes precedence in the default error
component and is the
error message from the latest failed async submission; it may already be a
translation key, but arbitrary backend text is not translated automatically. The
default `Content.Error` renders that value through `i18next` and offers a `Try again`
button when `submissionError` is present. The `onError` callback fires for failures
from both the SDK-managed FHIR submission path and a custom `onSubmit` callback.

`useQuestionnaireNavigation()` returns `isCurrentItemRequired`,
`isCurrentItemAnswered`, `isLastItem`, `currentItemNumber`, `totalItems`,
`showPrevious`, `isSubmitting`, `handleNext`, and `handlePrevious`. It must be used
inside `QuestionnaireNavigationProvider`, which is normally mounted by
`QuestionnaireFormProvider`.

The remaining public hooks support custom renderers:

- `useQuestionnaireNavigationState(...)` calculates the current-item flags and
  counters when the app owns the navigation provider.
- `useNavigationHandlers(...)` returns `handleNext` and `handlePrevious` for the
  current page/item state. Required answers are checked before advancing.
- `useInitialSelectedValues(...)` applies FHIR `answerOption.initialSelected` values
  and initializes enabled boolean items to `null` without triggering validation.

`QuestionnaireSubmitUtils.createQuestionnaireResponse(responses, pages, questionnaire)`
creates a completed FHIR `QuestionnaireResponse` with the questionnaire reference,
authored timestamp, and response items. It does not persist the response or add the
active patient subject; the SDK-managed submission path adds those app/client-owned
fields before saving.

`QuestionnaireFormValues`, `ResponseValues`, `ExtendedQuestionnaireItem`, and the
provider/context prop types are public TypeScript exports. The SDK extends FHIR
questionnaire items with optional `placeholder`, `helperText`, and
`answerOption.initialSelected` fields for rendering.

The SDK supplies layout primitives and FHIR mapping, not a router, persistence policy, analytics policy, or app-specific questionnaire schema.
