Add new form item to antd dynamic form list outside of the form - reactjs

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>

Related

Need to get form values outside the form in a modal

I am using ANTD React UI library.
<Modal
width="1100px"
centered
footer={null}
title={
<div className="d-flex align-items-center">
<div className="flex-grow-1">Record Profiles</div>
<div className="mr-4">
<Button
htmlType="submit"
type="primary"
onClick={() =>{this.SaveData(this.form.getFieldValue())}}
icon={<SaveOutlined />}
className="save_btn"
loading={this.state.saving}>
</Button>
<Button
onClick={() => { this.props.onCancel() }}
htmlType="button"
type="primary"
className="cancel_btn ml-2"
icon={<CloseCircleOutlined />}>
</Button>
</div>
</div>
}
visible={true}
closable={false}
okText="Yes"
cancelText="No"
maskClosable={false}
>
<Form
autoComplete="off"
layout="horizontal"
ref={(r) => this.form = r}
initialValues={this.props.record}
onFinish={this.SaveData}
>
.
.
.
</Form>
</Modal>
I want to call the save and close buttons on top of the side of the title. It is displaying correctly, but due to outside form functionalities don't work because the form values don't get outside. Is there any method to get the values outside or form submit?

antd disable field based on checkbox

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.

How to use <Form.List /> (or something similar) in 'formik-antd'?

I got simple question - Is it possible to use <Form.List /> in formik-antd? Tryed to find info about it but can't find anything in 3 hours. I need add dynamic fields in form, want to use <Form.List /> like in antd, but i use 'formik-antd'. looks like in 'formik-antd' no Form.List.. :( only Form.Item.
Any one know is the 'formik-antd' got <Form.List /> or something similar?
formik-antd is only used to make the components of antd compatible with formik, but something like Form.List isn't something that will be in formik-antd, but it comes from formik.
What you should use is FieldArray.
Example from docs:
Working codesandbox.
import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik';
// Here is an example of a form with an editable list.
// Next to each input are buttons for insert and remove.
// If the list is empty, there is a button to add an item.
export const FriendList = () => (
<div>
<h1>Friend List</h1>
<Formik
initialValues={{ friends: ['jared', 'ian', 'brent'] }}
onSubmit={values =>
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500)
}
render={({ values }) => (
<Form>
<FieldArray
name="friends"
render={arrayHelpers => (
<div>
{values.friends && values.friends.length > 0 ? (
values.friends.map((friend, index) => (
<div key={index}>
<Field name={`friends.${index}`} />
<button
type="button"
onClick={() => arrayHelpers.remove(index)} // remove a friend from the list
>
-
</button>
<button
type="button"
onClick={() => arrayHelpers.insert(index, '')} // insert an empty string at a position
>
+
</button>
</div>
))
) : (
<button type="button" onClick={() => arrayHelpers.push('')}>
{/* show this when user has removed all friends from the list */}
Add a friend
</button>
)}
<div>
<button type="submit">Submit</button>
</div>
</div>
)}
/>
</Form>
)}
/>
</div>
);
Just ran into the same Issue. My solution was to simply change the name in the import statement, just like so:
import {Form as antdForm} from 'antd';

Save values in a form in reactjs [duplicate]

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>
);
};

React Formik bind the external button click with onSubmit function in <Formik>

I'm trying to submit the form by using the external buttons which are located outside of <Form> or <Formik> tags
As shown in the following screenshot, my button is in Bootstrap > Modal Footer section and they are outside of form tag. I'm trying to submit the form when the user clicks on the Submit button.
Please see the similar code as the following. I uploaded it onto CodeSandbox.
function App() {
return (
<div className="App">
<Formik
initialValues={{
date: '10/03/2019',
workoutType: "Running",
calories: 300
}}
onSubmit={values => {
console.log(values);
}}
render={({ values }) => {
return (
<React.Fragment>
<Form>
Date: <Field name="date" />
<br />
Type: <Field name="workoutType" />
<br />
Calories: <Field name="calories" />
<br />
<button type="submit">Submit</button>
</Form>
<hr />
<br />
<button type="submit" onClick={() => this.props.onSubmit}>
Button Outside Form
</button>
</React.Fragment>
);
}}
/>
</div>
);
}
Since the button is outside of the form, it doesn't trigger Submit behaviour and I don't know how to connect this button's action and Formik OnSubmit method. If I moved that button inside form tag, it works as expected and I don't have to do anything special.
I tried to follow this SO's post React Formik use submitForm outside . But I really couldn't figure out how it works.
I tried to bind the button click action like onClick={() => this.props.onSubmit} as mentioned in the post. But it's not doing anything or showing any error.
Could you please help me how I can bind the Submit button outside of the form with 'OnSubmit' function in Formik?
It appears you have access to the submitForm method as a property of the argument passed to the render function. Simply call that with the button's onClick handler...
render={({ submitForm, ...restOfProps}) => {
console.log('restOfProps', restOfProps);
return (
<React.Fragment>
<Form>
Date: <Field name="date" />
<br />
Type: <Field name="workoutType" />
<br />
Calories: <Field name="calories" />
<br />
<button type="submit">Submit</button>
</Form>
<hr />
<br />
<button type="submit" onClick={submitForm}>
Button Outside Form
</button>
</React.Fragment>
);
}}
Formik's render give you a callback param handleSubmit. Assign this to the <button.
Since your button is not in the form, change its type to <button type="button"... and assign the onClick to onClick={handleSubmit}
Update the render as follow,
render={({ values, handleSubmit }) => {
return (
<React.Fragment>
<Form>
Date: <Field name="date" />
<br />
Type: <Field name="workoutType" />
<br />
Calories: <Field name="calories" />
<br />
<button type="submit">Submit</button>
</Form>
<hr />
<br />
<button type="button" onClick={handleSubmit}>
Button Outside Form
</button>
</React.Fragment>
);
}}
This is because the handleSubmit function is never called, replace onClick={() => this.props.onSubmit} with onClick={props.handleSubmit}
edit: since it looks like you need a little more directions, here is an edited version of the linked code sandbox, the correct prop is handleSubmit and you need to destructure it from the props just like you did with values.
https://codesandbox.io/s/qz2jnlp929
Just use onClick={handlesubmit} in your external Button component making sure to destructure the handlesubmit function from the Formik component. Please have a look;
<Formik
initialValues={{field: true}}
onSubmit={() => console("Submited via my onSubmit function")}
>
{({ handleSubmit }) => (
<Form>
<Field
name="field"
placeholder="Date"
/>
</Form>
<Button type="submit" onClick={handleSubmit}>
Save
</Button>
</Formik>

Resources