Form fields

Validation & submit

Required fields, patterns, ranges, dates and custom messages; submit only when valid.

Rules live in the schema

Add rules to a field's props: required, pattern, min / max, allowedValues, and for dates beforeToday / maxYearsAgo. Each rule has a message prop to replace the default text (requiredMessage, patternMessage, rangeMessage, ...).

The built-in action runValidation() checks every visible field. If something is wrong, the messages appear and the first wrong field gets the focus. If everything is fine, your onSubmit(entries) runs.

A message disappears as soon as the user edits that field.

Try it

Loading example…
Events0
Use the example — every action it runs shows up here with its data.

Code

Copy Full page.js into app/your-page/page.js of a Next.js app (withrcube-html, react-bootstrap and Bootstrap's CSS installed) — it runs as is. Or copy only the schema and keep your own page.

[
  {
    "type": "row",
    "id": "row-1",
    "children": [
      {
        "type": "column",
        "id": "c-name",
        "props": {
          "className": "col-12 col-md-6"
        },
        "children": [
          {
            "type": "InputField",
            "id": "name",
            "props": {
              "name": "name",
              "label": "Name",
              "required": true,
              "requiredMessage": "Please tell us your name."
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-email",
        "props": {
          "className": "col-12 col-md-6"
        },
        "children": [
          {
            "type": "InputField",
            "id": "email",
            "props": {
              "type": "email",
              "name": "email",
              "label": "Email",
              "required": true,
              "pattern": "[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}",
              "patternMessage": "That doesn't look like an email address."
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-age",
        "props": {
          "className": "col-6 col-md-3"
        },
        "children": [
          {
            "type": "InputField",
            "id": "age",
            "props": {
              "type": "number",
              "name": "age",
              "label": "Age",
              "required": true,
              "min": 18,
              "max": 99,
              "rangeMessage": "Age must be 18 to 99."
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-shoe",
        "props": {
          "className": "col-6 col-md-3"
        },
        "children": [
          {
            "type": "InputField",
            "id": "shoe",
            "props": {
              "type": "number",
              "name": "shoeSize",
              "label": "Shoe size",
              "allowedValues": [
                7,
                8,
                9,
                10,
                11
              ],
              "allowedValuesMessage": "We stock sizes 7–11."
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-birth",
        "props": {
          "className": "col-12 col-md-6"
        },
        "children": [
          {
            "type": "InputField",
            "id": "birth",
            "props": {
              "type": "date",
              "name": "birthDate",
              "label": "Date of birth",
              "required": true,
              "beforeToday": true,
              "maxYearsAgo": 120
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-zip",
        "props": {
          "className": "col-12 col-md-6"
        },
        "children": [
          {
            "type": "InputField",
            "id": "zip",
            "props": {
              "name": "zip",
              "label": "ZIP code",
              "mask": "#####",
              "pattern": "\\d{5}",
              "patternMessage": "Five digits, please."
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-topics",
        "props": {
          "className": "col-12 col-md-6"
        },
        "children": [
          {
            "type": "CheckboxGroupField",
            "id": "topics",
            "props": {
              "name": "topics",
              "label": "Topics",
              "required": true,
              "options": [
                "News",
                "Tips",
                "Offers"
              ]
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-terms",
        "props": {
          "className": "col-12"
        },
        "children": [
          {
            "type": "InputField",
            "id": "terms",
            "props": {
              "type": "checkbox",
              "name": "terms",
              "label": "I accept the terms",
              "required": true
            }
          }
        ]
      }
    ]
  },
  {
    "type": "row",
    "id": "row-buttons",
    "children": [
      {
        "type": "column",
        "id": "col-buttons",
        "props": {
          "className": "d-flex justify-content-end gap-2"
        },
        "children": [
          {
            "type": "ButtonField",
            "id": "clear",
            "props": {
              "text": "Clear",
              "onClick": "clearForm()"
            }
          },
          {
            "type": "ButtonField",
            "id": "check",
            "props": {
              "text": "Check without submitting",
              "variant": "outline-secondary",
              "onClick": "checkOnly()"
            }
          },
          {
            "type": "ButtonField",
            "id": "submit",
            "props": {
              "type": "submit",
              "text": "Submit",
              "onClick": "runValidation()"
            }
          }
        ]
      }
    ]
  }
]

Options used here

OptionWhat it does
required / requiredMessageMust be filled (checkbox: checked; group: at least one).
pattern / patternMessageRegular expression for the whole value.
min / max / rangeMessageNumber range.
allowedValues / allowedValuesMessageOnly these values are accepted.
numberMessageWhen a number field holds text that isn't a number.
beforeToday / beforeTodayMessageDate must be before today (also limits the date picker).
maxYearsAgo / maxYearsAgoMessageDate no more than N years ago.
requiredOptions / requiredOptionsMessageCheckbox group options that must all be checked.

Events

EventWhen it runsYour action receives
onSubmitrunValidation() found no errors.[{ name, email, age, ... }] — one object per entry.

Tips

  • Hidden fields (visibleWhen, hideNode, closed modals) are not validated.
  • To validate on your own button, call api.runValidation() in an action — it returns the entries or undefined.