This question already has answers here:
Save data in a form using reactjs
(2 answers)
Closed 2 years ago.
I have an application where user can submit data using a form. I'm using dynamic form where user can set how many forms he wants.
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) =>
!fieldsOnEdit.includes(index) ? (
<Space
key={field.key}
style={{ display: "flex", marginBottom: 8 }}
align="start"
>
<Form.Item
{...field}
name={[field.name, "first"]}
fieldKey={[field.fieldKey, "first"]}
rules={[
{ required: true, message: "Missing first name" }
]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit{setFieldOnEdit(index)}
</Button>
</Form.Item>
</Space>
) : (
<Edit value={formVal} keyForm={index} />
)
)}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</Form>
When i click on submit button appears <Edit value={formVal} keyForm={index} /> component where should appears corresponding value from the form. Now there is an issue:
when i save for example 2 forms, the second value overrides previous and so on.
I made this: value.users[value.users.length - 1].first, trying to set for every form corresponding value but it does not work.
Question: How to solve the issue, and when i will save a form to display the corresponding value in component?
demo: https://codesandbox.io/s/modest-austin-kqztw?file=/index.js:698-2310
The value is not overwritten, you are rendering always the same item.
You have the index of wanted item in keyFrom prop in your Edit component, just use it:
export const Edit = ({ value, keyForm }) => {
return (
<div>
edit mode
<p>value: {value.users[keyForm].first}</p>
</div>
);
};
Related
Based on this code snippet, I would like to reach and trigger the add property outside of the form. Any idea how can I do it?
<Form form={form} initialValues={initialValues} onFinish={onSubmit}>
<Form.List>
{(fields, { add, remove }) => (
<div>
{fields.map(field => (
<Form.Item {...field}>
<Input />
</Form.Item>
))}
</div>
)}
</Form.List>
// I don't want use this button here, inside the form list.
// I want invoke the add function from outside.
<Button type="link" onClick={() => add()}>
Add
</Button>
</Form>
// Or maybe from here
<Button type="link" onClick={() => add()}>
Add
</Button>
I am using Formik and Yup for a form control in React application. I use also Semantic UI. In the application, when I click the submit button, whereas I can read the values from FormField elements and see them on Console, I can not get the value of Date and Text Area elements and they appear blank on Console. How can I solve this out?
Here I define the intial values.
const initialValues = {
jobTitle: { id: "" },
deadline: "",
description: "",
};
Then here I try to get the values from form element
return (
<div>
<Card fluid>
<Card.Content>
<Card.Header>Create A New Job Ad</Card.Header>
<Divider inverted />
<Formik
initialValues={initialValues}
validationSchema={jobAdCreateSchema}
onSubmit={(values) => {
handleSubmit(values);
}}
>
{({ values, setFieldValue }) => (
<div>
<pre>{JSON.stringify(values, undefined, 2)}</pre>
<Form className="ui form">
<FormField>
<label>Job Title</label>
<Dropdown
selection
placeholder="Select a Job Title"
name="jobTitle"
fluid
options={jobTitleOption}
value={values.jobTitle.id}
onChange={(_, { value }) =>
setFieldValue("jobTitle.id", value)
}
/>
</FormField>
<FormField>
<label>Application Deadline</label>
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<label>Job Description</label>
<TextArea
name="description"
placeholder="Job Description"
style={{ minHeight: 100 }}
value={values.description}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<Button color="green" type="submit">
Submit
</Button>
</FormField>
</Form>
</div>
)}
</Formik>
</Card.Content>
</Card>
</div>
);
formik isn't defined, so your assigning an onChange function that doesn't exist.
Destructure handleChange from the argument, then assign it to the inputs like so:
{({ values, setFieldValue, handleChange }) => (
//...
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={handleChange}
/>
)}
Live demo
I'm using dynamic form in ant design library
I create checkbox and What I want to do is disable this timepicker field based on
the checkbox is checked or not
how can I do this
const Demo = () => {
const onFinish = (values) => {console.log(values)};
return (
<Form
>
{/* dynamically created card */}
<Form.List name="except">
{(fields, { add, remove }) => (
{fields.map((field) => (
<Space key={field.key}>
<MinusCircleOutlined
onClick={() =>remove(field.name)}/>
<Form.Item
{...field}
valuePropName={[field.name,'checked']} className="mb-3"
>
<Checkbox>مغلق</Checkbox>
</Form.Item>
{/* ------------- from_hour -------------*/}
<Form.Item
{...field}
name={[field.name,'from_hour']}
fieldKey={[field.fieldKey,'from_hour']}
>
<TimePicker
use12Hours
placeholder="اختر"
format="hh:mm A"
/>
</Form.Item>
</Space>
))}
)}
</Form.List>
</Form>
);
};
You need state. You can control the checked value of the checkbox and use that state to conditionally render another form item.
There is an example of this behavior in the docs.
I am using antd with react to develop an application.
<Form.List name="secondaryContacts">
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item
{...formItemLayoutWithOutLabel}
label={index === 0 ? "" : ""}
required={false}
key={field.key}
>
<Form.Item
{...field}
validateTrigger={["onChange", "onBlur"]}
rules={[
{
required: true,
validator: phoneNumberValidator
}
]}
>
<Input
placeholder="Secondary Contact"
addonAfter={
fields.length >= 1 ? (
<MinusCircleOutlined
onClick={() => {
remove(field.name);
}}
/>
) : null
}
/>
</Form.Item>
</Form.Item>
))}
<Form.Item {...formItemLayoutWithOutLabel}>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
<PlusOutlined /> Add Secondary Contact
</Button>
</Form.Item>
</div>
);
}}
</Form.List>;
Above is the code I am using to add dynamic form fields with validation using Form.List.
Now I have a specific scenario where I need to show 7 Sliders(https://ant.design/components/slider/) for the selected time slot and store them in an array, so I thought of using Form.List and keep all sliders inside just like above(except that it's static).
But I am not clear how I can achieve it with Form.List and there are very few examples on the internet.
I have a scenario where I need to have an array of forms and club them as an array using Form.List.
You can use the initialValue property to set the static data
Example:
const staticValue = [{ formItem1: 'value1', formItem2: 'value2'}];
<Form.List name="formListName" initialValue={staticValue}>
{(fields, { add, remove }, { errors }) => (
fields.map((field) => (
<>
<Form.Item {...field} name={[field.name, 'formItem1']}>
<Input placeholder="Field 1" />
</Form.Item>
...
You still need <Form> component
Try
<Form>
<Form.List>
</Form.List>
</Form>
I'm using Formik in my React and redux project, but Formik fields are not getting value and onChange field function not working!
this form is for editing a customer. I'm using Formik in another part of project and i don't have a problem. I don't know what to do?
<Formik
initialValues={props.selectedCustomer.id ? props.selectedCustomer : emptyCustomer}
validationSchema={customerValidationSchema}
onSubmit={async (values: ICustomer, actions: FormikActions<any>) => {
console.log(values)
try {
await postCustomer(values)
props.selectedCustomer.id ? enqueueSnackbar('success') : enqueueSnackbar('fail')
actions.resetForm()
getCustomers(pageNum, pageSize)
setAddDialog(false)
}
catch (error) {
enqueueSnackbar(error, { variant: 'default' })
}
}}
>
{() => (
<Form id="addCustomerForm">
<div id="addCustomerDiv" className={clsx({
[classes.noDisplay]: !addDialog
})}>
<Grid style={{marginRight: '0.5rem'}} container spacing={5}>
<Grid item xs={2}>
<Field
name="firstName"
render={({ field, form }: FieldProps<ICustomer>) => (
<TextField
margin="dense"
id="firstName"
label="firstName"
fullWidth
{...field}
error={form.errors.firstName && form.touched.firstName ? true : false}
/>
)}
/>
</Grid>
<Button
type='submit'
form="addCustomerForm"
color="primary"
variant="contained"
style={{marginTop: '3rem'}}
className={clsx({
[classes.noDisplay]: !addDialog
})}
>
submit
</Button>
</Grid>
</Grid>
</div>
</Form>
)}
</Formik>
what is the problem?
I added enableReinitialize in Formik component and it worked.