Validation Rules

Comprehensive validation system with 20+ built-in rules for strings, numbers, dates, and common formats.

Type-Safe Validation

All validation rules are fully type-checked, ensuring you can't assign the wrong value type to a rule. The system supports conditional validation, custom error messages, and async validation through services.

Basic Usage

json
{
  "id": "email",
  "blockType": "InputBlock",
  "metadata": {
    "label": "Email Address",
    "contextPath": "user.email"
  },
  "validations": [
    {
      "rule": "email",
      "message": "Please enter a valid email address"
    }
  ]
}

String/Character Validations

RuleValue TypeDescription
charMinLengthnumberMinimum string length
charMaxLengthnumberMaximum string length
charExactLengthnumberExact string length required
charMinMaxLength[min, max]Length must be between min and max
json
{
  "validations": [
    {
      "rule": "charMinLength",
      "value": 3,
      "message": "Must be at least 3 characters"
    },
    {
      "rule": "charMaxLength",
      "value": 50,
      "message": "Cannot exceed 50 characters"
    },
    {
      "rule": "charMinMaxLength",
      "value": [3, 50],
      "message": "Must be between 3 and 50 characters"
    }
  ]
}

Number Validations

RuleValue TypeDescription
numberMinnumberMinimum numeric value
numberMaxnumberMaximum numeric value
numberMinMax[min, max]Value must be between min and max
numberMinLengthnumberMinimum number of digits
numberMaxLengthnumberMaximum number of digits
json
{
  "validations": [
    {
      "rule": "numberMin",
      "value": 1,
      "message": "Must be at least 1"
    },
    {
      "rule": "numberMax",
      "value": 100,
      "message": "Cannot exceed 100"
    },
    {
      "rule": "numberMinMax",
      "value": [1, 100],
      "message": "Must be between 1 and 100"
    }
  ]
}

Pattern Validations

RuleValue TypeDescription
patternstring | RegExpCustom regex pattern
exactstring | number | booleanMust match exact value
json
{
  "validations": [
    {
      "rule": "pattern",
      "value": "^[A-Z][a-z]+$",
      "message": "Must start with capital letter, followed by lowercase"
    },
    {
      "rule": "exact",
      "value": "ACCEPT",
      "message": "You must type ACCEPT to continue"
    }
  ]
}

Date Validations

RuleValue TypeDescription
datePastMinDate | stringDate must be after minimum
datePastMaxDate | stringDate must be before maximum
dateFutureMinDate | stringDate must be after minimum (future)
dateFutureMaxDate | stringDate must be before maximum (future)
dateMinMax[Date, Date]Date must be in range
json
{
  "validations": [
    {
      "rule": "datePastMin",
      "value": "1900-01-01",
      "message": "Date must be after 1900"
    },
    {
      "rule": "dateFutureMin",
      "value": "2024-01-01",
      "message": "Date must be in 2024 or later"
    }
  ]
}

Common Format Validations

RuleDescriptionFormat
emailValid email addressuser@example.com
urlValid URLhttps://example.com
phoneUS phone number(555) 123-4567
zipCodeUS ZIP code12345 or 12345-6789
json
{
  "validations": [
    {
      "rule": "email",
      "message": "Please enter a valid email"
    }
  ]
}

// No value needed for format validations!

Conditional Validation

Apply validation rules only when certain conditions are met:

json
{
  "id": "business-name",
  "blockType": "InputBlock",
  "metadata": {
    "label": "Business Name",
    "contextPath": "businessName"
  },
  "validations": [
    {
      "rule": "charMinLength",
      "value": 1,
      "message": "Business name is required for business entities",
      "conditions": [
        {
          "matchType": "exact",
          "field": "entityType",
          "value": "business"
        }
      ]
    }
  ]
}

💡 Smart Validation

Validation only runs when entityType === "business". If the user selects "individual", this field doesn't need to be filled!

Multiple Validations

Stack multiple validation rules on a single field. They execute in order and stop at the first error:

json
{
  "id": "password",
  "blockType": "InputBlock",
  "metadata": {
    "label": "Password",
    "type": "password",
    "contextPath": "user.password"
  },
  "validations": [
    {
      "rule": "charMinLength",
      "value": 8,
      "message": "Password must be at least 8 characters"
    },
    {
      "rule": "pattern",
      "value": "(?=.*[A-Z])",
      "message": "Password must contain at least one uppercase letter"
    },
    {
      "rule": "pattern",
      "value": "(?=.*[0-9])",
      "message": "Password must contain at least one number"
    },
    {
      "rule": "pattern",
      "value": "(?=.*[!@#$%^&*])",
      "message": "Password must contain at least one special character"
    }
  ]
}

Complete Examples

Registration Form

json
{
  "blocks": [
    {
      "id": "email",
      "blockType": "InputBlock",
      "metadata": { "label": "Email", "contextPath": "user.email" },
      "validations": [
        {
          "rule": "charMinLength",
          "value": 1,
          "message": "Email is required"
        },
        {
          "rule": "email",
          "message": "Please enter a valid email address"
        }
      ]
    },
    {
      "id": "age",
      "blockType": "InputBlock",
      "metadata": { "label": "Age", "type": "number", "contextPath": "user.age" },
      "validations": [
        {
          "rule": "numberMin",
          "value": 18,
          "message": "You must be at least 18 years old"
        },
        {
          "rule": "numberMax",
          "value": 120,
          "message": "Please enter a valid age"
        }
      ]
    },
    {
      "id": "website",
      "blockType": "InputBlock",
      "metadata": { "label": "Website (optional)", "contextPath": "user.website" },
      "validations": [
        {
          "rule": "url",
          "message": "Please enter a valid URL (e.g., https://example.com)",
          "conditions": [
            {
              "matchType": "notNull",
              "field": "user.website"
            }
          ]
        }
      ]
    }
  ]
}

Async Validation

For validations that require API calls (like checking if an email already exists), use the asyncService property:

json
{
  "id": "email",
  "blockType": "InputBlock",
  "metadata": { "label": "Email", "contextPath": "user.email" },
  "validations": [
    {
      "rule": "email",
      "message": "Please enter a valid email"
    },
    {
      "rule": "custom",
      "asyncService": "checkEmailAvailability",
      "debounce": 500,
      "message": "This email is already registered"
    }
  ]
}

// In services:
{
  "checkEmailAvailability": {
    "type": "rest",
    "url": "/api/check-email",
    "method": "POST",
    "body": {
      "email": "{{context:user.email}}"
    }
  }
}

⚠️ Async Validation Notes

  • • Service must return { "valid": true } or { "valid": false }
  • • Use debounce to avoid excessive API calls
  • • Async validations run after sync validations pass

Validation Actions

Trigger actions based on validation state using isValid and isInvalid conditions:

json
{
  "id": "email",
  "blockType": "InputBlock",
  "metadata": { "label": "Email", "contextPath": "user.email" },
  "validations": [
    {
      "rule": "email",
      "message": "Invalid email"
    }
  ],
  "actions": [
    {
      "trigger": "onChange",
      "type": "conditional",
      "conditions": [
        {
          "matchType": "isValid",
          "field": "email"
        }
      ],
      "then": [
        {
          "type": "callApi",
          "service": "checkEmailAvailability"
        }
      ]
    }
  ]
}

Page-Level Validation

Validate all fields on the current page before allowing navigation:

json
{
  "id": "next-button",
  "blockType": "ButtonBlock",
  "metadata": { "label": "Next" },
  "actions": [
    {
      "type": "validateCurrentPage",
      "then": [
        {
          "type": "goToPage",
          "target": "page2"
        }
      ],
      "else": [
        {
          "type": "toast",
          "message": "Please fix the errors before continuing"
        }
      ]
    }
  ]
}

📚 Next Steps