Add option to validate a field when another field is changed
Problem Statement
Sometimes it is required to immediately validate a field if the value of another field has been changed. E.g. having two date fields, where one must be before/after the other, it is desired to validate one date based on the others current value.
Prefered API
Option 1
Validate a field, if the value of a specific other field changed:
createForm()({
fromDate: field.date().validateOnOtherFieldChange("toDate"),
toDate: field.date().validateOnOtherFieldChange("fromDate")
})
In this case it could also be desried to target multiple other fields. One way is to chain the validation triggers, the other one is to pass an array instead of a single value:
createForm()({
// chain
fromDate: field.date().validateOnOtherFieldChange("toDate")
.validateOnOtherFieldChange("anotherDate"),
// pass array
toDate: field.date().validateOnOtherFieldsChange(["fromDate", "anotherDate"]),
anotherDate: field.date();
})
Option 2
Validate a field, if any value in the form changed:
createForm()({
fromDate: field.date().validateOnAnyFieldChange(),
toDate: field.date().validateOnAnyFieldChange()
})
It might even make sense to implement both Options.
Option 2 should be a sperate ticket.
For Option 1 it might be better to move this feature from field level configuration to form level configuration:
- field level configuration should not be dependent on other fields
- this could also cause more complexity in the future (code and api wise)
Adapted approach for form level configuration
createForm()({
fromDate: field.date(),
toDate: field.date(),
// ...
}).withValidationTriggers({
fromDate: "toDate",
toDate: ["firstField", "secondField"]
});
But this doesn't look intuitive enough and on top of that it is not really fluent. It might be better to use a more generic approach, where triggers can be anything:
config.withTriggers({
fromDate: triggers()
.validationOnChangeFor("toDate")
.resetForReturnedFields(value => (value.getUTCFullYear() > 2010? "toDate" : undefined)),
});
(readout as: "fromDate triggers validation on change for toDate" or:
config.withTriggers({
toDate: triggers([
onChange().validationFor("fromDate"),
onBlur().resettingOfReturnedFields(value => (value.getUTCFullYear() > 2010? "anyField" : undefined))
])
});
useFluentForm now returns validateField and validateAllFields, so this behaviour can be implemented by hand:
const { values, touched, validateField } = useFluentForm(config);
useEffect(() => {
if(touched.toDate) {
validateField("toDate");
}
},[values.fromDate])
But I'll keep the ticket open for now, since it might be worth implementing triggers directly in react-fluen-form, because the solution above might not be straighforward. Also it could get quite complicated for the users to implement if the form is really big and has a lot of inter-field-dependencies.