marmelab / react-admin

A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design
http://marmelab.com/react-admin
MIT License
24.92k stars 5.24k forks source link

`<PasswordInput/>` or `<TextInput/>` has corrupted `validate` prop, if field is handled with `disabled` prop #9753

Open silversonicaxel opened 6 months ago

silversonicaxel commented 6 months ago

What you were expecting: A <PasswordInput/> is activated with a toggle that basically handle the password field disabled prop. If toggle is not active, <PasswordInput/> is disabled, otherwise enabled. The password field has a validate prop, that defines a rule for the field. Rule is minimum 8 characters. If not respected, a red error occurs.

Clicking saving button I expect to submit the form, with or without password enabled, and if enabled with password longer at least 8 characters.

Clicking saving button I expect not to submit the form, with password enabled and password length shorter than 8 characters.

What happened instead: With toggle enabled, password enabled and the password min length validation rule in place, I type a wrong password, long 3 characters. I submit the form with password rule not respected. The validate prop is ignored, form is submitted anyway.

If the disabled prop is never set in <PasswordInput/>, validate prop works as expected.

Steps to reproduce: Activate toggle for password field, type a short password, submit the form.

Related code:

  const { resetField } = useFormContext();
  const [resetPasswordEnabled, setResetPasswordEnabled] = useState(false);
  const onChangePasswordResetEnabled = useCallback<ChangeEventHandler<HTMLInputElement>>((event) => {
    resetField('password');
    setResetPasswordEnabled(event.target.checked);
  }, [resetField]);

  return (
    <TabbedForm>
      <TabbedForm.Tab label="Label">
        <BooleanInput
          label="Activate password change"
          source="activator"
          checked={resetPasswordEnabled}
          onChange={onChangePasswordResetEnabled}
        />
        <PasswordInput
          name="password"
          source="password"
          required={resetPasswordEnabled}
          disabled={!resetPasswordEnabled} // with this line fully removed, validate works
          validate={[minLength(8, 'Password at least 8 characters.')]}
        />
      </TabbedForm.Tab>
    </TabbedForm>
  );

Other information: No error occurs after clicking save button

Environment

erwanMarmelab commented 6 months ago

Hi @silversonicaxel, I'm not sure to understand when, where or how you want to use this code snippet. Could you apply it a Stackblitz please

silversonicaxel commented 6 months ago

@erwanMarmelab here my example: https://stackblitz.com/edit/github-eqexed-qzclqx?file=src%2Fposts%2FPostEdit.tsx

If you go to that link, follow the steps to see the two behaviours I am mentioning:

Wrong implementation (missing the disabled password prop), without the bug With the current and wrong implementation of the Stackblitz, in file src/posts/PostEdit.tsx at line 140 with disabled prop totally commented out. The outcome of the previous steps is the error, with the validate message requiring 8 characters to set a correct password field.

Correct implementation (with the disabled password prop), but WITH the bug Now, in order to see the bug, uncomment in file src/posts/PostEdit.tsx at line 140 the disabled prop. The outcome of the previous steps is a submitted form, with the element saved, and the validate rule ignored.

I hope things are more clear now.

erwanMarmelab commented 6 months ago

Confirmed, thanks for the report.

For the moment, you can validate your edit page by adding a form validation like this:

const validatePost = values => {
    const errors = {};
    if (values.activator && values.password.length < 8) {
        errors.password = 'Password at least 8 characters';
    }
    // other validations...
    return errors;
};

const PostEdit = () => {
    ...
    return (
        <Edit>
            <TabbedForm validate={validatePost}>
                ...
            </TabbedForm>
        </Edit>
    );
};
silversonicaxel commented 6 months ago

Thanks!