Home > Enterprise >  Validate other fluentui textfield based on the first one
Validate other fluentui textfield based on the first one

Time:01-07

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)

Codepen working example.

  • Related