# Dynamic Forms

The Dynamic Forms module presents one or more custom form screens to collect information from a user.

For an overview of this module and how it works, see [Forms and Data Entry](https://developer.incode.com/docs/forms-and-data-entry).

How you use this module depends on your integration pattern. Screens and questions can be defined in code or configured in the Dashboard. In most integrations, they come from your Incode Flow or Workflow configuration, so you add the module to an `IncdOnboardingFlowConfiguration` with an empty configuration and let the Dashboard drive the content, referencing the flow by ID. Define screens in code only when you need them client-side. See [Integration Approaches](https://developer.incode.com/docs/ios-flow-configuration).

**Availability:** All variants, iOS SDK version 5.31.0 or higher.

Use this module when:

- You need to collect additional structured data, such as typed questions and choices, during the flow.
- Your questionnaire varies by configuration and you do not want to ship an app update to change it.

For simple key/value session metadata that does not need a UI, use the [Custom Fields](https://developer.incode.com/docs/module-custom-fields) module instead.

## Add Dynamic Forms

Add the module to an `IncdOnboardingFlowConfiguration` with `addDynamicForms(configuration:)`. When the screens and questions are defined in your Incode Flow or Workflow configuration, pass a `DynamicFormConfiguration` with no screens and let Dashboard supply the content.

```swift
let config = DynamicFormConfiguration(screens: [
    DynamicFormScreen(
        title: "About you",
        hideTitle: false,
        questions: [
            DynamicFormQuestion(
                questionId: "occupation",
                question: "What is your occupation?",
                inputType: .text,
                isOptional: false
            )
        ]
    )
])

flowConfig.addDynamicForms(configuration: config)
```

## Configuration Options

The types below configure the module. The fields listed are the parameters of each type's public initializer.

| Type                       | Key Fields                                                                                                            |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `DynamicFormConfiguration` | `screens: [DynamicFormScreen]?`                                                                                       |
| `DynamicFormScreen`        | `title: String`, `hideTitle: Bool`, `questions: [DynamicFormQuestion]`                                                |
| `DynamicFormQuestion`      | `questionId: String`, `question: String`, `inputType: DynamicFormInputType`, `options: [String]?`, `isOptional: Bool` |

`DynamicFormConfiguration`, `DynamicFormScreen`, and `DynamicFormQuestion` expose only their initializer parameters below. The values aren't readable back from an existing instance.

## Result

The module reports completion through the onboarding delegate:

```swift
func onDynamicFormCompleted(_ result: DynamicFormsResult)
```

`DynamicFormsResult` fields:

- `answers: [DynamicFormQuestionnaireModel]`: The answered form entries, each pairing a question with its submitted answer.
- `error: IncdError?`: Set when the module could not complete; otherwise, `nil`.

Each entry in `answers` is a `DynamicFormQuestionnaireModel` and represents one answered question, carrying question metadata (`interviewId`, `questionId`, `question` text, `inputType`, `isOptional`) and answer data (`optionalAnswers`, `selectedAnswer`). These fields are internal to the SDK and aren't accessible from your app. They're included here for context on the model's structure, not as fields you interact with directly.

`inputType` is a `DynamicFormInputType`, one of:

| Field         | Field Value   |
| ------------- | ------------- |
| `text`        | `TEXT`        |
| `date`        | `DATE`        |
| `number`      | `NUMBER`      |
| `country`     | `COUNTRY`     |
| `email`       | `EMAIL`       |
| `phone`       | `PHONE`       |
| `cpf`         | `CPF`         |
| `nationality` | `NATIONALITY` |
| `selection`   | `SELECT`      |
| `yesno`       | `YESNO`       |

## Errors

Failures surface through the `error` field on `DynamicFormsResult`, typed as `IncdError`. This module does not define a module-specific error type.
