# Field: Custom validation

> Pass `validate` to check anything, including async lookups. Return a message to fail or nothing to pass. With `validationMode="onChange"` and `validationDebounceTime`, it runs while typing without firing on every key. Try “ada”.

Example: https://hextaui.com/docs/field/examples/custom-validation
Component docs: https://hextaui.com/docs/field.md

## Add this example

```bash
npx shadcn@latest add https://hextaui.com/r/field-custom-validation.json
```

This adds `components/examples/field/custom-validation.tsx` with the Field component and the HextaUI theme tokens.

## Source

```tsx title="components/examples/field/custom-validation.tsx"
"use client"

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

const taken = ["admin", "ada", "hexta"]

async function checkUsername(value: unknown) {
  const name = String(value ?? "")
    .trim()
    .toLowerCase()
  if (name.length === 0) {
    return null
  }
  if (!/^[a-z0-9_]+$/.test(name)) {
    return "Use letters, numbers and underscores only."
  }
  await new Promise((resolve) => setTimeout(resolve, 400))
  return taken.includes(name) ? `“${name}” is taken.` : null
}

export function FieldCustomValidation() {
  return (
    <Field
      validationMode="onChange"
      validationDebounceTime={300}
      validate={checkUsername}
      className="max-w-sm"
    >
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="Try “ada”" autoComplete="off" />
      <FieldDescription>Checked as you type.</FieldDescription>
      <FieldError />
    </Field>
  )
}
```

## Props in this example

### Field

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `validate` | `(value, formValues) => string \| string[] \| null \| Promise<…>` | – | Return one or more messages to fail, or nothing to pass. Async is supported. |
| `validationMode` | `"onSubmit" \| "onBlur" \| "onChange"` | `"onSubmit"` |  |
| `validationDebounceTime` | `number` | `0` | Milliseconds to wait between onChange validations. |

## More Field examples

- [Input](https://hextaui.com/docs/field/examples/input.md)
- [Validation](https://hextaui.com/docs/field/examples/validation.md)
- [Required and optional](https://hextaui.com/docs/field/examples/indicator.md)
- [Status](https://hextaui.com/docs/field/examples/status.md)
- [Character count](https://hextaui.com/docs/field/examples/counter.md)
- [Errors from a form library or server](https://hextaui.com/docs/field/examples/errors.md)
- [Checkboxes](https://hextaui.com/docs/field/examples/checkbox.md)
- [Choice cards](https://hextaui.com/docs/field/examples/choice-card.md)
- [Fieldset](https://hextaui.com/docs/field/examples/fieldset.md)
- [Responsive](https://hextaui.com/docs/field/examples/responsive.md)
- [Disabled](https://hextaui.com/docs/field/examples/disabled.md)
- [Long content](https://hextaui.com/docs/field/examples/long-content.md)
- [Right to left](https://hextaui.com/docs/field/examples/rtl.md)
