I have a question regarding validation with react and fluentui. I have following situation: 2 textfields and if one is filled in then the other should be filled in as well. Just validation is simple, I used onGetErrorMessage, which sets error message if on input the value does not meet the requirements. Now how can I set value on the other textfields, is it possible to trigger onGetErrorMessage of the textfield number two? For example if I have a reference or maybe some other way?
Const validate = (value: string, order: string) => string {
// if(order === 'one') => show error message that the second has to be filled in as well in case it is empty
// if(order === 'two') => show error message that the first has to be filled in in case it is empty
return value.length > 0 ? ‘’ : ‘Required’;
}
<TextField label = “Field 1” value = {field1} .... onGetErrorMessage={(value:string) => validate(value, 'one')} />
<TextField label = “Field 2” value = {field2} .... onGetErrorMessage={(value:string) => validate(value, 'two')} />
This would love to have as well like some generic solution... any idea how to achieve it?
Thanks in advance.
CodePudding user response:
I think you can't trigger onGetErrorMessage
by reference (I didn't find the way, share if you find out).
My idea is to create generic FormComponent
with following structure:
type Field = { options?: { label?: string }; validation?: string };
type Form<T> = { [P in keyof T]: Field };
type Props<T> = {
fields: Form<T>;
value: T & { [key: string]: string };
changeFormValue: (name: keyof Form<T>, value?: string) => void;
};
const FormComponent = <T extends unknown>({
fields,
changeFormValue,
value
}: Props<T>) => {
return (
<>
{(Object.keys(fields) as Array<keyof Form<T>>).map(field => {
const { validation, options } = fields[field];
return (
<TextField
label={options?.label}
value={value[field]}
errorMessage={validation} // Control validation
onChange={(_: any, value?: string) => changeFormValue(field, value)}
/>
);
})}
</>
);
};
Implementation:
import { Field, FormComponent } from 'common/form'
type Form = {
firstName: Field
lastName: Field
}
type FormValue = {
firstName: string
lastName: string
}
const HomeComponent = () => {
const [form, setForm] = React.useState<FormValue>({
firstName: "",
lastName: ""
});
// Place where you can control validation
const viewForm = ({ firstName, lastName }: FormValue): Form => ({
firstName: {
validation: firstName.length === 0 ? "Field is required" : undefined,
options: {
label: "First name"
}
},
lastName: {
validation:
lastName.length === 0 && firstName.length > 0
? "Field is required"
: undefined,
options: {
label: "Last name"
}
}
});
return (
<>
{FormComponent<FormValue>({
fields: viewForm(form),
changeFormValue: (field, value) => setForm({ ...form, [field]: value }),
value: form
})}
</>
);
};
If you need stronger validation or you have complex form, it's better to use some library. (Formik, TComb)