@crossroads-loyalty-solutions/formaggio
v0.2.2
Published
The cheesy form library
Readme
Installation
npm i @crossroads-loyalty-solutions/formaggioForms
Example
import {
Form,
isEmail,
required,
rules,
useFormField,
} from "@crossroads-loyalty-solutions/formaggio";
const TextInput = ({ name }) => {
const { dirty, errors, submitted, inputProps } = useFormField(name);
const className = (dirty || submitted) && errors.length ?
"form__text-input form__text-input--error" :
"form__text-input";
return <input type="text" className={className} {...inputProps} />;
};
const validateMyForm = rules([
required("name"),
required("email"),
isEmail("email")
]);
const MyForm = () => {
const [data, setData] = useState({});
const errors = validateMyForm(data);
return (
<Form
noValidate
name="my-form"
value={data}
onChange={setData}
onSubmit={console.log}
>
<TextInput name="name" />
<TextInput name="email" />
<button type="submit">Submit</button>
</Form>
);
};useFormField hook
The library provided React Hook useFormField is used to provide access to the
state for the given field name which include:
dirty: boolean: True if the user has modified this field.submitted: boolean: True if the user has tried to submit the form.errors: Array<ValidationError>: List of errors which apply to this field.inputProps: Object: Properties to apply to the<input />element.
The inputProps object contains id, name, value and an onChange
callback, the idea is to spread the properties into an <input />.
Form component
The <Form /> component provides the form state to any nested uses of
useFormField. It will wrap all its children in a <form /> tag.
Properties:
errors?: Array<ValidationErrors>: Any validation errors for this form.name?: string: This string will prefix anynameandidproperties in nested uses ofuseFormField.onChange: (FormData) => void: Callback for when the form data changes, these changes are performed immutably.onError?: (SyntheticEvent<HTMLFormElement>, Array<ValidationError>, FormData) => void: Callback fired instead ofonSubmitif there is an error in the form when the user tries to submit the form.onSubmit: (SyntheticEvent<HTMLFormElement>, FormData) => void: Callback fired with the current form data when the user submits the form.value: FormData: The data for the form.
Any properties not listed above will be propagated to the <form /> element.
To properly handle validation and onChange events in nested <input />
elements it is recommended to set the property noValidate on <Form />.
Validation
Validation is done using functions which take a value to validate and return a list of errors. The validation functions are created using rule-constructors or combinators.
Example
import {
conditional,
isEmail,
lengthGt,
required,
rules,
} from "@crossroads-loyalty-solutions/formaggio";
const validator = rules([
isEmail("email"),
required("firstname"),
required("lastname"),
conditional(s => s.password, lengthGt("password", 6)),
]);
const data = {
firstname: "foo",
lastname: "bar",
email: "foo@bar",
};
const errors = validator(data);
console.log(errors); // [{ error: "EMAIL", field: "email" }]Rules
Validation rules are constructed in a declarative manner using rule constructors and rule combinators.
A basic validator has the following type, where T is the type to be validated:
type Validator<T> = (t: T) => Array<ValidationError>;Errors
Errors are objects containing an error code and a field path. The field path is preserved through combinators and is used to determine which field caused the specific error. Additional properties are allowed but are error-specific.
type ValidationError = {
error: string,
field: string,
};