Skip to content
Advertisement

issue in dynamic Form List with collapse

I am stuck on implementing dynamic form submit. Here is my code.

I am receiving data from backend

    const dataFromBackend = [
      { id: 2, start: "2022-01-04T08:00:00.000Z", money: "500" },
      { id: 3, start: "2022-02-04T08:00:00.000Z", money: "1500" }
    ];

And trying to show that data to user in Collapse, and in collapse there are 2 forms (first one is for date, second one for money) that user can edit.

Also I have add button which allow user to add new collapse with empty inputs (first one is for date, second one for money).

After all user can add as much collapses as he/she wants and send all data to backend.

Here is the photo of final result. P.S. forms count in picture a little bit different, don’t worry about that 😉

I try to implement that in this way as says in antd docs:

    const BasicInformation = () => {
     const { Panel } = Collapse;

      const onSubmit = (data) => {
        console.log(data);
      };

      const dataFromBackend = [
        { id: 2, start: "2022-01-04T08:00:00.000Z", money: "500" },
        { id: 3, start: "2022-02-04T08:00:00.000Z", money: "1500" }
      ];
      return (
        <Form onFinish={(e) => onSubmit(e)}>
         <Form.List name="values">
           {(fields, { add }) => {
             return (
                <>
                  <Button
                    type="dashed"
                    onClick={() => {
                      add();
                    }}
                    block
                  >
                    Add
                  </Button>
                  <Collapse
                    accordion
                    style={{
                      background: "rgba(25, 103, 210, 0.08)",
                      border: "none"
                    }}
                  >
                    {dataFromBackend.map((data, idx) => (
                      <Panel
                        style={{ border: "none" }}
                        header={data.money}
                        key={`${data.id}`}
                      >
                       <div>
                         {fields.map((field) => (
                          <>
                             <Form.Item
                            {...field}
                            name={[field.name, "start"]}
                            label="Start"
                            fieldKey={[field.fieldKey, "start"]}
                          >
                            <DatePicker />
                          </Form.Item>
                          <Form.Item
                            {...field}
                            name={[field.name, "money"]}
                            label="Money"
                            fieldKey={[field.fieldKey, "money"]}
                          >
                            <Input />
                          </Form.Item>
                        </>
                      ))}
                    </div>
                  </Panel>
                ))}
              </Collapse>
            </>
          );
        }}
        </Form.List>

        <Button type="primary" htmlType="submit">
          send
         </Button>
        </Form>
      );
   };

But it not working correctly, when I am clicking on add button the forms were adding in collapse, but I need to add new collapse with that two forms.

Please help me fix that.

Thanks.

Answer

You need to create a new Collapse component on every iteration on the fields, also you need to convert start property in your dataFromBacked to moment object because antd’s DatePicker works with moment object as value. like this:

{fields.map((field, i) => (
    <Collapse
      key={i}
      accordion>
      <Panel ...>
        <Form.Item
          name={[field.name, 'start']}
          label="Start"
          fieldKey={[field.fieldKey, 'start']}>
            <DatePicker />
        </Form.Item>
        <Form.Item
          name={[field.name, 'money']}
          label="Money"
          fieldKey={[field.fieldKey, 'money']}>
            <Input />
        </Form.Item>
      </Panel>
    </Collapse>
))}

BTW in order to initialize your list with dataFromBackend you can use it as initialValue attribute on Form.List component. I’ve implemented an example Here on stackblitz you can check it out.

Advertisement