In my project I have antd form which used to add school details. In that form, I have ID field which need to be validated with back-end in onChange when input length = 5, whether that given ID is exists or not.
antd version 4.18.2
Field validations are handled via rules
attribute in Form.item
.
I use validator
function to handle this custom validation.
State values
const [idStatus, setIdStatus] = useState(false); // this value is get by API call.
const [validateStatus, setValidateStatus] = useState("");
Form ID field
<Form form={form} name="form" onFinish={onFinish}>
<Row className="applicationFormContent">
<Col span={8}>
<Form.Item
name="schoolId"
label="School Id"
validateStatus={validateStatus}
rules={[
{
required: true,
message: "Please Provide School ID!"
},
{
len: 5,
message: "School ID must have 5 digits"
},
{
validator: validateId // validator is a function used for custom validation.
}
]}
>
<Input
type={"number"}
maxLength={5}
placeholder="Id - 00000 format"
onChange={(e) => checkSchoolId(e.target.value)}
/>
</Form.Item>
</Col>
</Row>
</Form>
Function triggered in onChange
const checkSchoolId = async (value) => {
try {
if (value.length === 5) {
let response = await checkId(value);
console.log("-----", response.response?.data?.idExists);
setIdStatus(response.response?.data?.idExists);
} else {
setValidateStatus("error");
}
} catch (err) {
console.log(err);
}
};
Validator function used in rules
const validateId = (rule, value) => {
if (idStatus) {
// value return from API call.
setValidateStatus("error");
return Promise.reject("Census Id Already Exist");
} else {
setValidateStatus("success");
return Promise.resolve();
}
};
Problem:
when the input length = 5, I get the value from backend and it updates the state. But validator function is not triggered with that update. Which means Form input is not being re-rendered when update the state variable. i logged the values and updated values are shown as it is.
But when I type one more number (input-lenght=6), show both validations and then delete one character (now input-length=5), it shows the validation get from back-end value.
how to solve this?
example code sandbox
In my project I have antd form which used to add school details. In that form, I have ID field which need to be validated with back-end in onChange when input length = 5, whether that given ID is exists or not.
antd version 4.18.2
Field validations are handled via rules
attribute in Form.item
.
I use validator
function to handle this custom validation.
State values
const [idStatus, setIdStatus] = useState(false); // this value is get by API call.
const [validateStatus, setValidateStatus] = useState("");
Form ID field
<Form form={form} name="form" onFinish={onFinish}>
<Row className="applicationFormContent">
<Col span={8}>
<Form.Item
name="schoolId"
label="School Id"
validateStatus={validateStatus}
rules={[
{
required: true,
message: "Please Provide School ID!"
},
{
len: 5,
message: "School ID must have 5 digits"
},
{
validator: validateId // validator is a function used for custom validation.
}
]}
>
<Input
type={"number"}
maxLength={5}
placeholder="Id - 00000 format"
onChange={(e) => checkSchoolId(e.target.value)}
/>
</Form.Item>
</Col>
</Row>
</Form>
Function triggered in onChange
const checkSchoolId = async (value) => {
try {
if (value.length === 5) {
let response = await checkId(value);
console.log("-----", response.response?.data?.idExists);
setIdStatus(response.response?.data?.idExists);
} else {
setValidateStatus("error");
}
} catch (err) {
console.log(err);
}
};
Validator function used in rules
const validateId = (rule, value) => {
if (idStatus) {
// value return from API call.
setValidateStatus("error");
return Promise.reject("Census Id Already Exist");
} else {
setValidateStatus("success");
return Promise.resolve();
}
};
Problem:
when the input length = 5, I get the value from backend and it updates the state. But validator function is not triggered with that update. Which means Form input is not being re-rendered when update the state variable. i logged the values and updated values are shown as it is.
But when I type one more number (input-lenght=6), show both validations and then delete one character (now input-length=5), it shows the validation get from back-end value.
how to solve this?
example code sandbox
Share Improve this question edited Apr 22, 2022 at 12:59 James Z 12.3k10 gold badges27 silver badges47 bronze badges asked Apr 22, 2022 at 11:45 DevThimanDevThiman 1,1381 gold badge14 silver badges28 bronze badges3 Answers
Reset to default 5There is a method named form.validateFields(['array of input names need to validate'])
provided by antd Form
for field validations.
With that I was able to re-execute the validation of the schoolId
input when response e for idStatus
inside a useEffect
as below.
useEffect(() => {
// manually validate the field since input is not validated by form once state update.
form.validateFields(['schoolId']);
}, [idStatus]);
With the above way, we can manually trigger validation for particular Form.Item
in antd Form wherever we want.
it's hard to say and please don't leave unlike if it's not true. but when you pass validator method in your rules like below:
validator: validateId
acutely you reference your validator into your method and the data and state that use in this method get initial state from first and never update. for solving this instead of passing reference to validator pass it as arrow-function and also pass your idStatus stat as arguments of method. something like bellow
validator: (rule, value) => validateId(rule, value, idStatus)
with this approach you force your application to run this method each time want check validator.
useEffect(() => {
form.validateFields(['schoolId']);
}, [form.getFieldValue("schoolId")]);