# Form validations

All form fields support custom validations, which are configured with the `validation` property. **If a validation does not pass, it means the form is filled incorrectly and a validation error is displayed.**

The `validation` property takes an array of validations, and all of them must pass for the validation of that field to succeed.

{% hint style="info" %}
Validators are conditionals. Each `validator` has the similar expressions you would write for a `SHOW` / `ENABLE` conditional — most commonly built from the `field(...)` chain, optionally combined with `and` / `or` / `not`. See [Conditionals](/v2.0/technical/guides/configuration/events/conditionals.md) for the full list of helpers.
{% endhint %}

The `validation` property is only used for content checks on a filled-in value. To mark a field as mandatory, use the separate `required` property on the field configuration.

**Example:**

In this example, we have a father's date-of-birth field with two custom validations:

1. The inputted date must be before today.
2. The inputted date must be before the inputted child's date of birth, `child.dob`.
   1. For the validation to work correctly, we expect that the `child.dob` field is configured on the form (but it may be on a different page).

```typescript
import { field, defineFormPage, FieldType } from '@opencrvs/toolkit/events'

export const father = defineFormPage({
  id: 'father',
  title: {
    defaultMessage: "Father's details",
    description: 'Form section title for fathers details',
    id: 'form.section.father.title'
  },
  fields: [
    // ... other fields
    {
      id: 'father.dob',
      type: FieldType.DATE,
      validation: [
        {
          message: {
            defaultMessage: 'Must be a valid Birthdate',
            description: 'This is the error message for invalid date',
            id: 'event.birth.action.declare.form.section.person.field.dob.error'
          },
          validator: field('father.dob').isBefore().now()
        },
        {
          message: {
            defaultMessage: "Birth date must be before child's birth date",
            description:
              "This is the error message for a birth date after child's birth date",
            id: 'event.birth.action.declare.form.section.person.dob.afterChild'
          },
          validator: field('father.dob').isBefore().date(field('child.dob'))
        }
      ]
    }
  ]
})
```

Now both validations must succeed for the validation to pass, otherwise we will display a validation error on the UI and consider the declaration as incomplete.

Validation errors on the declaration form are shown both on the form page, and the review page:

{% columns %}
{% column %}

<figure><img src="/files/sonl1WlIXzW3N0elPuab" alt=""><figcaption><p>Form page</p></figcaption></figure>
{% endcolumn %}

{% column %}

<figure><img src="/files/rhzGzIyemarlYhRkzPZT" alt=""><figcaption><p>Review page</p></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

### ValidationConfig schema

## The ValidationConfig object

```json
{"openapi":"3.1.0","info":{"title":"OpenCRVS API","version":"2.0.0"},"components":{"schemas":{"ValidationConfig":{"type":"object","properties":{"validator":{"description":"Conditional expression that must hold for the field value to be considered valid.","$ref":"#/components/schemas/Conditional"},"message":{"description":"Error message displayed when the validator does not hold.","$ref":"#/components/schemas/TranslationConfigOutput"}},"required":["validator","message"],"additionalProperties":false,"description":"Validation rule applied to a form field. The validator is a conditional expression that must hold for the field value to be considered valid."},"Conditional":{"description":"JSON schema conditional configuration"},"TranslationConfigOutput":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the translation referred in translation CSV files"},"defaultMessage":{"type":"string","description":"Default translation message"},"description":{"type":"string","description":"Describe the translation for a translator to be able to identify it."}},"required":["id","defaultMessage","description"],"additionalProperties":false,"description":"Translation configuration"}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.opencrvs.org/v2.0/technical/guides/configuration/events/declaration-and-forms/form-validations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
