How to use formik with Antd Design Form? - reactjs

I am trying to implement formik validation with Ant design form, formik is able to capture the input/selected data but when I click onSubmit, it doesn't print anything in console.
export default function SearchForm() {
const formik = useFormik({
initialValues: {
city: "",
checkIn: "",
},
onSubmit: (values) => {
console.log(values)
},
});
//console.log(formik.values)
return (
<Form onSubmit={formik.handleSubmit}>
<FormLabel>Select City</FormLabel>
<Form.Item>
<Select
name="city"
value={formik.values.city}
placeholder="Please select a country"
onChange={(value) => formik.setFieldValue("city", value)}
>
<Select.Option value="mumbai">Mumbai</Select.Option>
<Select.Option value="bengaluru">Bengaluru</Select.Option>
<Select.Option value="delhi">Delhi</Select.Option>
<Select.Option value="hyderabad">Hyderabad</Select.Option>
<Select.Option value="chennai">Chennai</Select.Option>
</Select>
</Form.Item>
<FormLabel>Check-In-Date</FormLabel>
<Form.Item>
<DatePicker
name="checkIn"
value={formik.values.checkIn}
format={dateFormat}
onChange={(value) => formik.setFieldValue("checkIn", value)}
/>
</Form.Item>
<SubmitButton htmlType="submit">Book Now</SubmitButton>
</Form>
);
}
And by giving values, the placeholder text is not visible, and also in DatePicker, it is saving as Moment Object.

You can add Validation Schema in useFormik and import Yup, like this :
import * as Yup from 'yup';
const FormSchema = Yup.object().shape({
title: Yup.string().required('Please enter notification title')
});
<Formik
validationSchema={FormSchema}>
<Form>
<div className='grid-row'>
<div className='grid-1'>
<Field name='title' required={true} label='Title'component={Input} />
</div>
</Form>
</Formik>

finally, I got an answer!! When we use the Ant design form, it works a little different from the normal form, instead of using onSubmit we have to use onFinish and generally you pass value and function to capture event.target.value in normal form but in Ant design form we have to pass onChange={(value) => formik.setFieldValue("checkIn", value)} and it will simply capture the change.
<Form onFinish={formik.handleSubmit}>
<FormLabel>Select City</FormLabel>
<Form.Item>
<Select
name="city"
placeholder="Please select a country"
onChange={(value) => formik.setFieldValue("city", value)}
>
<Select.Option value="mumbai">Mumbai</Select.Option>
<Select.Option value="bengaluru">Bengaluru</Select.Option>
<Select.Option value="delhi">Delhi</Select.Option>
<Select.Option value="hyderabad">Hyderabad</Select.Option>
<Select.Option value="chennai">Chennai</Select.Option>
</Select>
</Form.Item>
<FormLabel>Check-In-Date</FormLabel>
<Form.Item>
<DatePicker
name="checkIn"
format={dateFormat}
onChange={(value) => formik.setFieldValue("checkIn", value)}
/>
</Form.Item>
<SubmitButton htmlType="submit">Book Now</SubmitButton>
</Form>

Related

Populate react formik form with existing data

i am new to react, can anyone explain to me how can i manipulate or repopulate my existing form from backend data in react.
I am trying to edit and existing item in the inventory that i wanna change values for. i am using formik with react and formik grid. for data i am using AXIOS.
What i am trying to do is to get edit a specific entry from my database which has changed values. it's like trying to update values
<Formik
validationSchema={schema}
initialValues={{
name: "",
numberOfSets: "0",
sortValue: "0",
boxType: "",
price: "",
photo: "",
}}
onSubmit={({
name,
numberOfSets,
sortValue,
boxType,
price,
photo,
}) => {
boxService.addBox(
name,
numberOfSets,
sortValue,
boxType,
price,
photo
);
alert("Box added Successfully!"); // Box or Gift it's same thing
window.location.reload(false);
}}
>
{({
values,
errors,
touched,
handleBlur,
handleSubmit,
setFieldValue,
}) => {
return (
<Form
form={form}
name="edit-gift"
onFinish={handleSubmit}
{...layout}
labelAlign="left"
>
// These are the fields i am trying to manipulate
<Form.Item name="name" label="Name">
<Input
name="name"
title="Product Name"
dataIndex="name"
key="productName"
value={values.name}
onChange={(e) => setFieldValue("name", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Name"
/>
{errors?.name && touched?.name && (
<Text type="danger">{errors?.name}</Text>
)}
</Form.Item>
<Form.Item name="numberOfSets" label="Number of Sets">
<Input
name="numberOfSets"
type="number"
value={values.numberOfSets}
onChange={(e) =>
setFieldValue("numberOfSets", e.target.value)
}
onBlur={handleBlur}
placeholder="Please enter Number of Sets"
/>
{errors?.numberOfSets && touched?.numberOfSets && (
<Text type="danger">{errors?.numberOfSets}</Text>
)}
</Form.Item>
<Form.Item name="sortVlaue" label="Sort Value">
<Input
name="sortVlaue"
type="number"
value={values.sortValue}
onChange={(e) => setFieldValue("sortVlaue", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter soring value"
/>
{errors?.numberOfBoxes && touched?.numberOfBoxes && (
<Text type="danger">{errors?.numberOfBoxes}</Text>
)}
</Form.Item>
<Form.Item name="boxType" label="Type">
<Select
value={values.boxType}
onChange={(value) => setFieldValue("boxType", value)}
onBlur={handleBlur}
placeholder="Please enter Box Type"
>
<Select.Option value="reward">Reward</Select.Option>
<Select.Option value="doublerandom">
Double Random
</Select.Option>
</Select>
{errors?.boxType && (
<Text type="danger">{errors?.boxType}</Text>
)}
</Form.Item>
<Form.Item name="price" label="Price">
<Input
name="price"
title="Product Price"
dataIndex="price"
key="price"
value={values.price}
onChange={(e) => setFieldValue("price", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Price"
/>
{errors?.price && touched?.price && (
<Text type="danger">{errors?.price}</Text>
)}
</Form.Item>
<Form.Item name="photo" label="Product Picture">
<div className="dropzone-container">
{values.photo && <img src={values.photo} alt=""></img>}
{!values.photo && (
<Dropzone
onDrop={(acceptedFiles) => {
acceptedFiles.map((file) => {
console.log(file);
});
let fr = new FileReader();
fr.onload = function () {
setFieldValue("photo", fr.result);
setFieldValue("imgName", acceptedFiles[0].name);
console.log(acceptedFiles[0]);
};
fr.readAsDataURL(acceptedFiles[0]);
}}
accept={{ "image/*": [] }}
maxSize={1000000}
>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>
Drag 'n' drop some files here, or click to
select files
</p>
<aside>
Tips: The size ratio of the photo is: 750:216,
the maximum recommended size is 1M, and the
format is: .jpg, .jpeg, .png
</aside>
</div>
</section>
)}
</Dropzone>
)}
</div>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Cofirm save
</Button>
</Form.Item>
</Form>
);
}}
</Formik>
You could either:
rerender the Formik component when your data is available and pass it to the initialValues prop by doing something like
results?.data && <Formik initialValues={{...}}>...</Formik>
or set the values manually with setValues after the data is available
const {setValues, values, ...} = useFormik({...});
useEffect(() => {
setValues(results?.data); // use any fields from your data
}, [results]} // this is the data from your api

How to get error message by getFieldError in AntD Form?

I'm validating form with Ant Design but I have a problem with getFieldError(). I need to get the error messages by the field name of Form.Item but it not works.
Here's my code not works below:
...
<Form form={form} name="login_form" onFinish={onFinish} scrollToFirstError>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Password cannot be empty!',
},
]}
help='' // hide validating message.
>
<>
{({ getFieldError }) => console.log(getFieldError('password'))}
//it not logging anything when submit form trigger error
<Input.Password placeholder="Enter your password" />
</>
</Form.Item>
</Form>
How can I solved this problem?
Your console.log will invoke, every time your component renders, so you need to rerender your component whenever validation applies on the form. To handle this situation you can use render prop with Form component, like this:
function CustomFormItem({ error, ...other }) {
console.log(error)
return <Input.Password placeholder="Enter your password" {...other} />;
}
function MyForm() {
const [form] = Form.useForm();
const onFinish = (values) => {
console.log(values);
};
return (
<Form
form={form}
name="login_form"
onFinish={onFinish}
scrollToFirstError
>
{(values,formInstance) => {
return (
<>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Password cannot be empty!',
},
]}
help="" // hide validating message.
>
<CustomFormItem error={formInstance.getFieldError('password')} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</>
);
}}
</Form>
);
}
Consider that with above implementation, render prop will call with every change on the form.
Use can use getFieldError(); like the code example below
Function as Child Component is not working perfectly inside <Form.Item> component as of now.
<Form {...layout} form={form} name="control-hooks" onFinish={onFinish}>
{(values, formInstance) => {
console.log(formInstance.getFieldError("password")[0]);
return (
<>
<Form.Item
name="password"
label="Password"
rules={[
{
required: true
}
]}
>
<Input />
</Form.Item>
</>
);
}}
</Form>

Form not Submitting in React using Formik and Yup

I'm using Autocomplete component in Material UI and I'm using Formik and Yup for validations.
My problem is that when I submit my values and console it. It doesn't appear which means it doesn't conform to its yup validation.
Pls check my codesandbox here
Click here
<Formik
validationSchema={citySchema}
initialValues={{ city_id: [{ id: null, name: "" }] }}
onSubmit={submit}
>
{({ handleChange, values, setFieldValue, touched, errors }) => (
<Form>
<Autocomplete
id="city_id"
name="city_id"
options={cities}
getOptionLabel={(option) => option.name}
style={{ width: 300 }}
onChange={(e, value) => {
setFieldValue("city_id", value);
}}
renderInput={(params) => (
<TextField
label="City"
variant="outlined"
helperText={touched.city_id && errors.city_id}
error={touched.city_id && Boolean(errors.city_id)}
{...params}
/>
)}
/>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</Form>
)}
</Formik>
Your validationSchema requires a name but your code never supplies it.
Either make it optional or add a name input field.
An easy way to debug this is to print out the errors formik is supplying you:
<Form>
<pre>{JSON.stringify(errors, null, 2)}</pre>
<Autocomplete
...

Reactjs antd defaultValue return undefined

im trying to make an edit function, the problem come when im trying to get the value from the form, say a user is editing his name, but he does not edit his address, this will make address is undefined even though i already set a defaultValue inside it, this works before in my non antd form, here is my code
form :
<Form onFinish={this.edit}>
<Typography>Email</Typography>
<Form.Item
name="email"
>
<Input defaultValue={user.Email} value={user.Email} className="email form-control col-sm-6"/>
</Form.Item>
<Typography>Full Name</Typography>
<Form.Item
name="name"
>
<Input defaultValue={user.FullName} value={user.FullName} className="email form-control col-sm-6"/>
</Form.Item>
<Typography>Admin</Typography>
<Form.Item
name="admin"
>
{
(user.IsAdministrator)
? <div>
<Select value="yes">Admin
<Select.Option value="no">Not Admin</Select.Option>
</Select>
</div>
: <div>
<Select value="no">Not admin
<Select.Option value="yes">Admin</Select.Option>
</Select>
</div>
}
</Form.Item>
<Typography>Active Status</Typography>
<Form.Item
name="aktif"
>
{
(user.IsActive)
? <Toggle className="switch-lg" checked/>
: <Toggle className="switch-lg"/>
}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login col-md-10">Submit</Button>
and here is how i get the value :
edit(values){
const name = values.name
const aktif = values.aktif
const index = this.state.id
console.log(values)
}
thanks before, anyhelp will be appreciated
As mentioned in the docs,
You cannot set value for each form control via value or defaultValue prop, you should set default value with initialValues of Form.
Example below:
<Form
onFinish={onFinish}
initialValues={{
residence: ['zhejiang', 'hangzhou', 'xihu'],
prefix: '86',
}}
>

Other validation message is triggering instead of my message when using Ant design getFieldDecorator

I am using Ant design and this is my form when I click on save I am getting this type of validation msg instead of red bordered Antd validation msg
I want validation error like this which is shown in AntD documents.
https://codesandbox.io/s/do52z
I have writter my function like this
<Form id="myForm" onSubmit={this.handleSubmit}>
<Form.Item label="Code">
<CustomInput
form={this.props.form}
type="text"
disabled={this.state.disableFields}
name="code"
id="code"
placeholder=""
required={true}
errorMsg={"Please input code!"}
/>
</Form.Item>
</Form>
This is my custom Input
const CustomInput = ({
form, id, name, placeholder, required, errorMsg, type, disabled,}: Props) => {
return form.getFieldDecorator(id, {
rules: [
{
required: required,
message: errorMsg
}
]
})(
<Input
type={type}
name={name}
id={id}
disabled={disabled}
placeholder={placeholder}
className={name === "code" ? "code-input" : "input-box"}
/>
);
};
export default CustomInput;
and this is my save button
<Button
className="save-btn"
htmlType="submit"
form="myForm"
>
Save
</Button>
I think I am missing something little here. Thanks in advance
Ant design input doesn't have required prop..
Required prop should be give inside form.item rules prop.
Since you have given reqired to input tag it will cause Chrome to display a prompt that the user to fill out the field.
Update based on comment
Move formitem tag inside custominput component and try again.
<Form id="myForm" onSubmit={this.handleSubmit}>
<CustomInput
form={this.props.form}
type="text"
disabled={this.state.disableFields}
name="code"
id="code"
placeholder=""
required={true}
errorMsg={"Please input code!"}
/>
</Form>
..
const CustomInput = ({
form, id, name, placeholder, required, errorMsg, type, disabled,}: Props) => {
return(
<Form.Item label="Code">
{form.getFieldDecorator(id, {
rules: [
{
required: required,
message: errorMsg
}
]
})(
<Input
type={type}
name={name}
id={id}
disabled={disabled}
placeholder={placeholder}
className={name === "code" ? "code-input" : "input-box"}
/>
)}
</Form.Item>
)
};

Resources