I am trying to disable the form submit button until the validation is fully passed.
I have come across the threads regarding this topic.
This thread helps to trigger validation without display of UI errors: https://github.com/ant-design/ant-design/issues/25993
The below code works within the hoc of my footer button wrapper, but it is verifying for all fields to be touched and even applicable for non-required fields, which is not right and expected.
<Form.Item shouldUpdate>
{() => (
<Button
type="primary"
htmlType="submit"
disabled={
!!form
.getFieldsError()
.filter(({ errors }) => errors.length).length
}
>
Log in
</Button>
)}
</Form.Item>
Unfortunately, https://github.com/ant-design/ant-design/issues/23281 thread is full of Chinese and I cannot understand it.
My existing form.validateFields refers to formInstance, but it is referring to: InternalFormInstance.
How to import this and validate? Is it really supported in antd 4 version?
CodeSandbox link: https://codesandbox.io/s/gallant-merkle-21izz?file=/src/withFormWrapperHOC.tsx
Example code as a reference will be helpful!
The form validation miserably fails when select list is included. Form onChange or onChangeValues don't work; when we dig more the !form.isFieldsTouched(true) is always true even when there is no validation rule associated with Select List.
Ref ticket: https://github.com/ant-design/ant-design/issues/8436
It looks like Antd has some open issues with Rc-select api integrations and also which is not exposed.
Should we really consider Antd or any other form validation?
For disabling validation on first render you can use Ref workaround
const isMounting = React.useRef(false);
useEffect(() => {
if (isMounting.current) {
const disableStatus = !!form
.getFieldsError()
.filter(({ errors }) => errors.length).length;
setIsDisabled(disableStatus);
}
else {
isMounting.current = true
}
}, [form]);
Another option would to disable login button till all the form inputs are filled and then validate with Login
import React, { useState } from "react";
import { Button, Form, Select } from "antd";
import "antd/dist/antd.css";
const { Option } = Select;
export function withFormWrapper(WrappedComponent: any) {
return (props: any) => {
const [form] = Form.useForm();
const [isDisabled, setIsDisabled] = useState(true);
function fieldIsEmpty(field) {
let fieldValue = form.getFieldValue(field.name.join("."));
return (
fieldValue === undefined || [].concat(fieldValue).join().trim() === ""
);
}
function fieldHasError(field) {
return field.errors.length > 0;
}
function isValid() {
const fields = form
.getFieldsError()
.filter((field) => fieldIsEmpty(field) || fieldHasError(field));
console.log(fields);
setIsDisabled(fields.length > 0);
}
const validate = () => {
form
.validateFields()
.then((values: any) => {
console.log("success");
})
.catch((errorInfo: any) => {
console.log("failure");
});
};
return (
<Form form={form} onChange={isValid}>
<WrappedComponent {...props} />
<Form.Item name="gender" label="Gender" rules={[{ required: true }]}>
<Select
placeholder="Select a option and change input text above"
onChange={isValid}
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
<Form.Item>
<Button
type="default"
htmlType="submit"
onClick={() => form.resetFields()}
>
Cancel
</Button>
</Form.Item>
<Form.Item shouldUpdate>
{() => (
<Button
onClick={validate}
type="primary"
htmlType="submit"
disabled={isDisabled}
>
Log in
</Button>
)}
</Form.Item>
</Form>
);
};
}
Here working example
With Form.Provider
onFormChange
validation can be fired for Select Component
import React, { useState } from "react";
import { Button, Form, Select } from "antd";
import "antd/dist/antd.css";
const { Option } = Select;
export function withFormWrapper(WrappedComponent: any) {
return (props: any) => {
const [form] = Form.useForm();
const [isDisabled, setIsDisabled] = useState(true);
function fieldIsEmpty(field) {
let fieldValue = form.getFieldValue(field.name.join("."));
return (
fieldValue === undefined || [].concat(fieldValue).join().trim() === ""
);
}
function fieldHasError(field) {
return field.errors.length > 0;
}
function isValid() {
const fields = form
.getFieldsError()
.filter((field) => fieldIsEmpty(field) || fieldHasError(field));
setIsDisabled(fields.length > 0);
}
const validate = () => {
form
.validateFields()
.then((values: any) => {
console.log("success");
})
.catch((errorInfo: any) => {
console.log("failure");
});
};
return (
<Form.Provider onFormChange={isValid}>
<Form form={form}>
<WrappedComponent {...props} />
<Form.Item
name="gender"
label="Gender"
rules={[{ required: true }]}
shouldUpdate
>
<Select
placeholder="Select a option and change input text above"
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
<Form.Item name="Tags" label="Tags" shouldUpdate>
<Select
mode="tags"
style={{ width: "100%" }}
placeholder="Tags Mode"
onChange={handleChange}
>
{children}
</Select>
</Form.Item>
<Form.Item>
<Button
type="default"
htmlType="submit"
onClick={() => form.resetFields()}
>
Cancel
</Button>
</Form.Item>
<Form.Item shouldUpdate>
{() => (
<Button
onClick={validate}
type="primary"
htmlType="submit"
disabled={isDisabled}
>
Log in
</Button>
)}
</Form.Item>
</Form>
</Form.Provider>
);
};
}
Here working example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With