Portal Community

Full ValidationConfig Interface

// packages/types-js/src/validation.types.ts

interface ValidationConfig {
  // ── Presence ──────────────────────────────────
  required?: boolean;
  requiredMessage?: string;

  // ── String length ──────────────────────────────
  minLength?: number;
  minLengthMessage?: string;
  maxLength?: number;
  maxLengthMessage?: string;

  // ── Numeric range ──────────────────────────────
  min?: number;
  minMessage?: string;
  max?: number;
  maxMessage?: string;

  // ── Format ────────────────────────────────────
  pattern?: string;           // JavaScript regex string (no delimiters)
  patternMessage?: string;
  email?: boolean;
  emailMessage?: string;
  url?: boolean;
  urlMessage?: string;

  // ── Date bounds ────────────────────────────────
  minDate?: string;           // ISO date string or "today"
  minDateMessage?: string;
  maxDate?: string;
  maxDateMessage?: string;

  // ── Selection cardinality ──────────────────────
  minSelections?: number;
  minSelectionsMessage?: string;
  maxSelections?: number;
  maxSelectionsMessage?: string;

  // ── Data table rows ────────────────────────────
  minRows?: number;
  minRowsMessage?: string;
  maxRows?: number;
  maxRowsMessage?: string;

  // ── File upload ────────────────────────────────
  fileTypes?: string[];       // MIME types: ["image/png", "application/pdf"]
  fileTypesMessage?: string;
  maxFileSizeMb?: number;
  maxFileSizeMbMessage?: string;

  // ── Custom rules ───────────────────────────────
  customRule?: string | CustomRuleConfig;
  customRules?: CustomRuleConfig[];   // Multiple custom rules

  // ── Conditional validation ─────────────────────
  requiredWhen?: string;      // Expression — field becomes required when true
  validateWhen?: string;      // Expression — skip validation unless this is true
}

interface CustomRuleConfig {
  name?: string;              // Name of a registered validator
  expression?: string;        // Inline expression (returns true if valid)
  message: string;            // Error message when rule fails
  async?: boolean;            // Flag if the validator is async
}

Complete Example — Text Field

{
  "id": "company-registration",
  "type": "text",
  "label": "Company Registration Number",
  "validation": {
    "required": true,
    "requiredMessage": "Company registration number is required",
    "minLength": 6,
    "minLengthMessage": "Registration numbers are at least 6 characters",
    "maxLength": 12,
    "maxLengthMessage": "Registration numbers are at most 12 characters",
    "pattern": "^[A-Z0-9\\-]+$",
    "patternMessage": "Only uppercase letters, numbers and hyphens allowed",
    "customRule": {
      "name": "registrationNumberChecksum",
      "message": "Invalid registration number — checksum failed",
      "async": false
    }
  }
}

requiredWhen — Conditional Required

Use requiredWhen to make a field required only when another field has a specific value. The expression is evaluated against the current form values:

// VAT number is required only if vatRegistered is true
{
  "id": "vat-number",
  "type": "text",
  "label": "VAT Registration Number",
  "visibilityRule": "values['vatRegistered'] === true",
  "validation": {
    "requiredWhen": "values['vatRegistered'] === true",
    "pattern": "^[A-Z]{2}[0-9]{9,12}$",
    "patternMessage": "Enter a valid EU VAT number (e.g. GB123456789)"
  }
}

validateWhen — Skip Validation Conditionally

Use validateWhen to skip all validation rules unless a condition is met. This is useful for optional sections that are only relevant in certain scenarios:

// Only validate the director details if the entity type is a company
{
  "id": "director-name",
  "type": "text",
  "label": "Director Name",
  "validation": {
    "required": true,
    "validateWhen": "values['entityType'] === 'company'"
  }
}

Combining Multiple Custom Rules

Use customRules (plural) to chain multiple custom validators on a single field. All must pass for the field to be valid:

{
  "id": "bank-account",
  "type": "text",
  "label": "Bank Account Number",
  "validation": {
    "required": true,
    "customRules": [
      {
        "name": "ibanFormat",
        "message": "Must be a valid IBAN format"
      },
      {
        "name": "ibanChecksum",
        "message": "IBAN checksum is invalid",
        "async": false
      },
      {
        "name": "bankAccountAllowlisted",
        "message": "This bank account is not in the approved list",
        "async": true
      }
    ]
  }
}