[](https://github.com/oaf-project/oaf-react-final-form/actions/workflows/main.yml) [





An opinionated form library.
* TypeScript + React Final Form
* Strict type safety
* Validation built with io-ts
* Accessible by default
* By default we render accessible form labels and validation feedback (with aria-invalid and aria-labelledby)
* We follow the guidance from https://www.tpgi.com/required-attribute-requirements/
* We use the novalidate attribute on the form element to disable browsers’ client-side validation. Instead, we implement custom validation and accessible error messaging.
* To ensure most screen readers won’t default to announcing required form controls as invalid, we use aria-invalid="false". We update this to true if the current value (or lack thereof) of a required control does not pass validation.
* We use aria-describedby on required form controls to point to the element that contains the inline error message.
* We wait until the control has lost focus before marking a form control as invalid and displaying the inline error message. We do this by defaulting React Final Form's validateOnBlur option to true. See https://github.com/final-form/final-form/issues/250. As a consequence, we include work-arounds for https://github.com/final-form/final-form/issues/213 and https://github.com/final-form/react-final-form/issues/458
* After a failed form submission, we move focus to the first invalid form element (using https://github.com/oaf-project/oaf-side-effects)
* We follow the advice from https://webaim.org/techniques/formvalidation/
``shyarn
yarn add oaf-react-final-form
Usage
`typescript
// First, we define the form codec using io-ts.
// See https://github.com/gcanti/io-ts#the-idea
//
// formCodec is just a convenience function over the top of
// intersection, type, partial and readonly from io-ts.
// See https://github.com/gcanti/io-ts#mixing-required-and-optional-props
const codec = formCodec({
optional: {
foo: t.string,
},
}); // We derive React components for our form elements from the form codec. This
// gives us some type-safety benefits when rendering these form elements (below).
const { Form, Input, Select } = elementsForCodec(codec);
type FormData = t.TypeOf;
const onSubmit = (formData: FormData): SubmissionResponse => {
// Here we are guaranteed that
formData has been parsed by our form codec.
// We can return submission errors here if necessary.
return undefined;
}; const form = (
name attr must be one of the values from the form codec.
The type and required attrs must be compatible with the corresponding property from the form codec.
* Because foo is optional in the codec, required must be either undefined or false.
* Because foo is a string in the codec, type cannot be one of the numeric input types (number or range).
*/}
);
``See Form.test.tsx for more examples.