Form contains two items, both of it is an input field that accepts a number. I need to check if the value entered in the first input (start) is always less than the second (end) or else, show a validation error.
The above is wrapper inside antd form and each of it is a Form.Item
.
I need show validation message like this,
Code:
const App = () => {
const [start, setStart] = useState(1);
const [end, setEnd] = useState(2);
const formRef = useRef();
const handleSubmit = () => {
if (end < start) {
console.log("End cannot be lesser than start");
} else if (end === start) {
console.log("End cannot be same as start");
} else {
console.log("Added :)", start, end);
}
};
return (
<Form
onFinish={handleSubmit}
layout="vertical"
ref={formRef}
requiredMark={false}
>
<div>
<Form.Item
name="formStart"
rules={[
{
required: true,
message: "Please select a form start"
}
]}
>
<InputNumber
placeholder="Start"
min={1}
max={100}
onChange={(e) => setStart(e)}
/>
</Form.Item>
<Form.Item
name="formEnd"
rules={[
{
required: true,
message: "Please select a form end"
}
]}
>
<InputNumber
placeholder="End"
min={1}
max={100}
onChange={(e) => setEnd(e)}
/>
</Form.Item>
<Form.Item>
<button htmlType="submit">Submit</button>
</Form.Item>
</div>
</Form>
);
};
If there is an alternative instead of using setState, It can also use ref (formRef.current)
Code sandbox: https://codesandbox.io/s/basic-usage-antd-4-21-0-forked-4sri66?file=/demo.js
CodePudding user response:
You can use useRef
:
import React, { useRef } from "react";
Define ref variables:
const start = useRef();
const end = useRef();
Pass the refs to the inputs:
<InputNumber placeholder="Start" min={1} max={100} ref={start} />
<InputNumber placeholder="End" min={1} max={100} ref={end} />
Access the input values:
if (end.current.value < start.current.value) {
// some code
}
You can also set the default values by adding the defaultValue
attribute. For example:
<InputNumber placeholder="Start" min={1} max={100} ref={start} defaultValue={1} />
CodePudding user response:
For custom validations or conditional validations we need to include 'validator'
inside our rules
as below as per the antd
docs.
<Form.Item
name="formEnd"
rules={[
{
required: true,
message: "Please select a form end"
},
({ getFieldValue }) => ({
validator(rule, value) {
// from 'getFieldValue("fieldName")' we can get the current value of that field.
if (value < getFieldValue("formStart")) {
// value = currentValue of this field. with that we can do validations with other values in form fields
return Promise.reject("End range must be greater than start"); // The validator should always return a promise on both success and error
} else if (value === getFieldValue("formStart")) {
return Promise.reject("End cannot be same as start");
} else {
return Promise.resolve();
}
}
})
]}
>
With this approach, you can achieve above validation without use of internal state and also without useRef
.
Few points for when use antd form
- antd form has
Form.useForm
which create Form instance to maintain data store. With this we can easily get the current form state like values, errors etc. - It also has
form.submit()
function which trigger the given function for FormonFinish
. So we can use that for SUBMIT Btn onClick.
Here is the full demo code in codesandbox.
Check this form/API for more antd Form
props and functions.