CxJS

ValidationGroup

import { ValidationGroup } from 'cx/widgets'; Copied

The ValidationGroup is a container that tracks the validation state of all form fields inside it. It reports whether all fields are valid and can propagate settings like disabled, readOnly, or viewMode to all child fields.

<div class="flex flex-col gap-4">
  <ValidationGroup valid={m.valid} visited={m.visited} asterisk>
    <LabelsTopLayout vertical>
      <TextField label="First Name" value={m.data.firstName} required />
      <TextField label="Last Name" value={m.data.lastName} required />
      <TextField label="Email" value={m.data.email} required />
    </LabelsTopLayout>
  </ValidationGroup>
  <div class="flex items-center gap-4">
    <Button
      onClick={(e, { store }) => {
        if (!store.get(m.valid)) {
          store.set(m.visited, true)
          return
        }
        MsgBox.alert("Form submitted successfully!")
      }}
    >
      Submit
    </Button>
    <span
      class="text-sm"
      text={expr(m.valid, (v) =>
        v ? "Form is valid ✓" : "Please fill all required fields",
      )}
    />
  </div>
</div>
Please fill all required fields

Error Summary

The errors binding collects all validation errors from child fields. Use it with a Repeater to display an error summary.

<div>
  <div class="mb-3">Enter X and Y so that X + Y = 20.</div>
  <div
    class="flex gap-16 pl-4 border-2 rounded p-4 items-center"
    className={{
      "border-red-600": falsy(m.valid),
      "border-green-500": truthy(m.valid),
    }}
  >
    <ValidationGroup valid={m.valid} errors={m.errors} visited>
      <LabelsTopLayout class="-mt-4">
        <NumberField
          label="X"
          value={m.x}
          required
          requiredText="Please enter X."
          style="width: 80px"
        />
        <NumberField
          label="Y"
          value={m.y}
          required
          requiredText="Please enter Y."
          style="width: 80px"
        />
      </LabelsTopLayout>
      <Validator
        value={{ x: m.x, y: m.y }}
        onValidate={({ x, y }) => {
          if (x + y !== 20) return "X + Y must equal 20"
        }}
        visited
      />
    </ValidationGroup>
    <ul class="text-red-700 text-sm" visible={falsy(m.valid)}>
      <Repeater records={m.errors} recordAlias={m.$error}>
        <li text={m.$error.message} class="list-disc!" />
      </Repeater>
    </ul>
    <div class="text-green-600 text-sm" visible={truthy(m.valid)}>
      Form is valid!
    </div>
  </div>
</div>
Enter X and Y so that X + Y = 20.
  • Please enter X.
  • Please enter Y.
  • X + Y must equal 20

Configuration

Validation State

PropertyTypeDescription
validbooleanBinding set to true if all child fields are valid
invalidbooleanBinding set to true if any child field has a validation error
errorsValidationErrorData[]Binding to store the array of validation errors
visitedbooleanIf true, forces all children to show validation errors
isolatedbooleanIf true, isolates children from outer validation scopes

Field State Propagation

PropertyTypeDefaultDescription
disabledbooleanfalseDisables all inner elements that support disabled
enabledbooleanOpposite of disabled
readOnlybooleanfalseMakes all inner elements read-only
viewModebooleanfalseSwitches all inner fields to view mode
strictbooleanfalseForces children to respect group-level flags
asteriskbooleanfalseAdds red asterisk for all required fields
tabOnEnterKeybooleanfalseMoves focus to the next field when Enter is pressed