lenses-ppx
lenses-ppx copied to clipboard
Consider adding a way to get/list all the fields and iterate them ?
Sometimes when working with forms one might want to loop over all the fields and render any errors they have.
Perhaps this library could generate some kind utilities for this in addition to getters&setters of individual fields?
For example maybe I'd like to do this in onSubmitFail
of reforms:
/** Handle failures detecred *before* onSubmit (mutation call).ShiftsListGraphQL
Useful for displaying errors from local validations of ShiftForm. */
let onSubmitFail = ({state}: ShiftForm.onSubmitAPI) => {
Js.log4("onSubmitFail", state.values, state.formState, state.fieldsState)
let collectErrorString = field =>
ShiftForm.getFieldState(~schema, ~values=state.values, ~field)
->Belt.Option.map((_, fieldState) =>
switch (fieldState) {
| ShiftForm.Error(s) => Some(s)
| _ => None
}
);
// build these into Js.Dict along their errors to render something to the user
// eg; "there are errors in these fields"
collectErrorString(Field(Name))
collectErrorString(Field(BrandId))
collectErrorString(Field(Is_draft))
collectErrorString(Field(ShiftId))
collectErrorString(Field(Shift_visibility))
collectErrorString(Field(Contract_type))
collectErrorString(Field(Matchmaking_industry))
collectErrorString(Field(Matchmaking_category))
collectErrorString(Field(Name))
collectErrorString(Field(Description))
collectErrorString(Field(LocationId))
collectErrorString(Field(Custom_address))
collectErrorString(Field(Languages))
collectErrorString(Field(Requirements))
collectErrorString(Field(Cover_photo))
collectErrorString(Field(Schedule_type))
collectErrorString(Field(Pricing_type))
collectErrorString(Field(Rate_hourly_amount))
collectErrorString(Field(Rate_fixed_amount))
collectErrorString(Field(Times))
collectErrorString(Field(Cnt))
};
however, the code can get quite tedious quite fast with larger forms.
Or maybe I should be approaching this problem differently?
Actually this is already ReForm does internally, the trick is to iterate over the validation schema! https://github.com/Astrocoders/reform/blob/master/packages/bs-reform/src/ReFormNext.re#L57
To have a way to iterate over the list of GADTs directly is very cumbersome, see here https://discuss.ocaml.org/t/packing-gadt-constructors-in-iterable-data-structure/2678/4
Sorry for the late response 😅 Thanks for using ReForm, FYI we are almost getting ready to launch ReFormNext as stable with a hooks API
I've been using this pattern:
let mergeWholeState =
(
formState,
~schema:
ReSchema.Make(OnboardingProfileFormTypes.StateLenses).Validation.schema(
option(ProfileFastForm.meta),
),
) => {
open OnboardingProfileFormTypes.StateLenses;
let Schema(schema) = schema;
let changeField = field => {
let currentState = currentWholeFormState->React.Ref.current;
let newState = currentState->set(field, formState->get(field));
currentWholeFormState->React.Ref.setCurrent(newState);
};
schema->Belt.Array.forEach(validator => {
switch (validator) {
| ProfileFastForm.Form.Validation.StringNonEmpty({field})
| ProfileFastForm.Form.Validation.StringRegExp({field})
| ProfileFastForm.Form.Validation.StringMin({field})
| ProfileFastForm.Form.Validation.StringMax({field})
| ProfileFastForm.Form.Validation.Email({field}) =>
let currentState = currentWholeFormState->React.Ref.current;
let newState =
currentState->set(field, formState->get(field)->Js.String.trim);
currentWholeFormState->React.Ref.setCurrent(newState);
| ProfileFastForm.Form.Validation.IntMin({field})
| ProfileFastForm.Form.Validation.IntMax({field}) => changeField(field)
| ProfileFastForm.Form.Validation.FloatMin({field})
| ProfileFastForm.Form.Validation.FloatMax({field}) =>
changeField(field)
| ProfileFastForm.Form.Validation.Custom({field}) => changeField(field)
| ProfileFastForm.Form.Validation.NoValidation({field}) =>
changeField(field)
}
});
Hooks.OnboardingFormData.persist(currentWholeFormState->React.Ref.current)
|> ignore;
};
though the list of validators is pretty huge it's mostly boilerplate and if you are using ocamllsp you can use the destruct
code action to generate it automatically for you