---
# System prepended metadata

title: Building form controls
tags: [zeta-dom-react]

---

---
tags: zeta-dom-react
---

# Building form controls

The library does not ship built-in field components.

Instead, components are built using the `useFormField` hook.

The hook takes `FormFieldProps<T>` as the first argument, where it looks for parent `FormContext` instance visible in the context, and handles validations and as well as emitting events.


## Creating field component

Here is an example of a simple input box:

```typescript
function TextField(props: FormFieldProps<string>) {
    const { value, error, setValue, elementRef } = useFormField(props, '');
    return (
        {/* Provider ref so that form.element() and form.focus() helper methods will work */}
        <label ref={elementRef}>
            <input name={props.name}
                   value={value}
                   disabled={!!props.disabled}
                   onChange={e => setValue(e.target.value)} />
            {error && props.showErrorMessage !== false &&
                <div className="error">{error}</div>}
        </label>
    );
}
```

Value is updated through the `setValue` dispatcher where it will trigger `dataChange` and `validate` events on the `FormContext` instance.

If `props.onValidate` is supplied, validation are executed and result is populated to `error` state.

For some frequently used properties defined in `FormFieldProps<T>`, it is up to your implemention on how to handle:

| Property           | Description                   |
| ------------------ | ----------------------------- |
| `name`             | Provide name to input element |
| `label`            | Field label                   |
| `disabled`         | Whether the input is disabled |
| `required`         | Whether the input is required |
| `showErrorMessage` | Show error message            |


## Field validation

By default `useFormField` only checks for `required` property. Any other validations have to be done through the `onValidate` option.

However, it is useful to validators activated through meaningful props instead of having to passing validator functions to `onValidate` every time using the component.

For example, you might want these props available for a text field:

```typescript
interface TextFieldProps extends FormFieldProps<string> {
    required?: boolean;
    maxLength?: number;
    pattern?: string;
}
```
See [Parameterizing validations](/MqseTJw2RvyBFND7iITRFw#Parameterizing-validations) for more details.

## Examples

- [Text box](/GCsLwFamS8SR5GCtENrv1Q#TextField)
- [Checkbox list](/GCsLwFamS8SR5GCtENrv1Q#MultiChoiceField)
