Ricardinho
Ricardinho

Reputation: 609

reset form.fields in antd reactjs

Im using form list from antd with react.js https://ant.design/components/form/#Form.List

I have a simple form list here. I can add and remove fields.

Sometimes I want to reset the form remove items Ive added.

const [form] = Form.useForm();
...
<Form form={form} name="control-hooks">
    <Form.List name="fruits">
        {(fields, { add, remove }) => (
            <>
                {fields.map(({ key, name, ...restField }) => (
                    <Row key={key}>
                        <Col span={24}>
                            <Form.Item {...restField} name={[name, 'color']}>
                                <Select placeholder="Select fruit">{
                                    fruits.map((fruit, index) =>
                                        <Option key={index} value={fruit.color}>
                                            {fruit.color}
                                        </Option>
                                    )
                                }
                                </Select>
                            </Form.Item>
                            <Form.Item {...restField} name={[name, 'quantity']} initialValue={1}>
                                <InputNumber placeholder="Quantity" />
                            </Form.Item>
                            <Button onClick={() => remove(name)}>Remove</Button>
                        </Col>
                    </Row>
                ))}
                <Form.Item>
                    <Button type="dashed" onClick={() => add()}>
                        Add
                    </Button>
                </Form.Item>
                <Form.Item>
                    <Button type="primary" htmlType="submit">
                        Submit
                    </Button>
                </Form.Item>
            </>
        )}
    </Form.List>
</Form>
...
<Button type="primary" onClick={resetForm}>Reset from outside</Button>

This is my try:

const resetForm = () => {
  form.resetFields();
}

Any ideas how I can make it? Thank you

Edit: I added more detailed explanation enter image description here

Edit2

https://codesandbox.io/s/priceless-robinson-6q577?file=/src/index.js

I tried to make a example and for some reason it worked .... what is the difference???

Edit3

Solution:

I found the problem! It was the initialValue. If I have initialValue in any of my Form.Item, antd will not remove those dynamically added fields. Thanks for the help

Upvotes: 1

Views: 11871

Answers (3)

Subrato Pattanaik
Subrato Pattanaik

Reputation: 6049

Antd Form.List component provides a way to add the same fields again in the form dynamically. The children of the component is expecting to be used as function of a child just like render prop. So, this render function is going to be invoked by antd Form.List component. We don't have controlled over the invocation of the function of a child.

The type of children of Form.List is given below. I have taken from here.

export interface FormListFieldData {
  name: number;
  key: number;
}

export interface FormListOperation {
  add: (defaultValue?: StoreValue, insertIndex?: number) => void;
  remove: (index: number | number[]) => void;
  move: (from: number, to: number) => void;
}

export interface FormListProps {
 // other types
 children: (
    fields: FormListFieldData[],
    operation: FormListOperation,
    meta: { errors: React.ReactNode[]; warnings: React.ReactNode[] },
  ) => React.ReactNode;
}

So, we can use the fields, operation and meta data in the children function.


Your below snippet, doesn't do that Antd Form.List is expected to do. You're not calling a children function, its Antd Form.List component who is going to call the children function with some defined props that is mentioned in the above type snippet.

 const [formFields, setFormFields] = useState([]); // you don't need any state.
 ...
 <Form.List>
     {formFields => (  // error, it should be fields that antd expects
       <div>
          {formFields.map(formField => (
          <Form.Item {...formField}>
            <Input />
          </Form.Item>
        ))}
      </div>
     )}
  </Form.List>

Basic example of Form.List with reset and no inputs is hidden below, please unhide to be visible:

// don't run it, it just to hide long snippets
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button, Space } from 'antd';
import {  PlusOutlined } from '@ant-design/icons';

const Demo = () => {
  const [form] = Form.useForm();
  const onFinish = values => {
    console.log('Received values of form:', values);
    
  };

  const onReset = () => {
    form.resetFields()
  }

  return (
    <Form form={form} name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
      <Form.List name="hello">
        {(fields, { add }) => (
          <>
            {fields.map(({ key, name,  }) => (
              <Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
                <Form.Item
                 
                  name={[name, 'first']}
                  rules={[{ required: true, message: 'Missing first name' }]}
                >
                  <Input placeholder="First Name" />
                </Form.Item>
                <Form.Item
                 
                  name={[name, 'last']}
                  rules={[{ required: true, message: 'Missing last name' }]}
                >
                  <Input placeholder="Last Name" />
                </Form.Item>
              </Space>
            ))}
            <Form.Item>
              <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
                Add field
              </Button>
            </Form.Item>
          </>
        )}
      </Form.List>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
        <Button type="secondary" onClick={onReset}>
          Reset
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, document.getElementById('container'));
// dont run it

form.resetFields() will clear the input values and remove the inputs from the form if the Form.list has a name property/attribute associated with it.

Upvotes: 1

Asgar
Asgar

Reputation: 439

can you try this?

form.setFieldsValue({ fruits:[] });

Upvotes: 0

hazimdikenli
hazimdikenli

Reputation: 6019

The values provided as the initialValues should be used by the reset function.

<Form
 ...
        initialValues={{first_name: 'John'}}
/>

If you want to change some of them afterwards the way to go is;

form.setFieldsValue({ first_name: 'John' });

to do that your fields should have the name properties defined here.

<Form.Item
  name="first_name"

Upvotes: 5

Related Questions