Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set value dynamically inside Form.List using setFieldsValue in Antd 4?

<Form>
   <Form.List name="projects">
   {fields => 
   ...
      fields.map(field => <Form.Item name={[field.key, "type"]} hidden={true} initialValue={type} />)
   ...
   }
   </Form.List>

</Form>

Whenever type changes, I want to set Item value dynamically. I think I can get form instance using the useForm and use the setFieldsValue like below.

form = useForm()
onChange(type) {
   form.setFieldsValue(/* values here */)
}

But I am not sure how to use the form.setFieldsValue to refer item inside Form.List.

Who can give me solution?

like image 327
Adelin Ionut Avatar asked Sep 02 '20 17:09

Adelin Ionut


2 Answers

The Antd form list creates an array of item objects. Then it is necessary to locate the position of the object within the array that contains the item that will have the value changed.

Return all values for form items:

const fields = form.getFieldsValue()

Retrieve the array containing the form list objects:

const {projects} = fields

Pass the object's position within the array and change the item to the new value:

Object.assign(projects[key], {type: value})

Then pass the new array value to the form:

form.setFieldsValue({projects})

Here is a complete example:

import React from 'react';
import { Form, Select, Button } from 'antd'

const { Option } = Select

export default function FormProject() {
  const [ form ] = Form.useForm()

  const onChange = (value, key) => {
    const fields = form.getFieldsValue()
    const { projects } = fields
    Object.assign(projects[key], { type: value })
    form.setFieldsValue({ projects })
  }

return (
  <Form
    form={form}
    initialValue={{type: "type_1"}}
    >
    <Form.List name="projects">
      {(fields, { add, remove }) => (
        <div>
          <Form.Item>
            <Button type="dashed" onClick={add} >
              Add
            </Button>
          </Form.Item>
          {fields.map(field => (
            <div>
            <Form.Item name={[field.key, "type"]} hidden={true} />
            <Form.Item noStyle name={[field.name, 'id']}>
              <Button type="dashed" onClick={remove} >
                Remove
              </Button>
            </Form.Item>
            <Form.Item
              {...field}
              name={[field.name, 'type_project']}
              label="Tipo"
              fieldKey={[field.fieldKey, 'type_project']}
            >
              <Select onChange={e => onChange(e, field.key)}>
                <Option value="type_1">Type 1</Option>
                <Option value="type_2">Type 2</Option>
                <Option value="type_1">Type 2</Option>
              </Select>
            </Form.Item>
            </div>
          ))}
        </div>
      )}
    </Form.List>
  </Form>
  );
}
like image 184
Marcelo Avatar answered Oct 16 '22 17:10

Marcelo


One of the ways to manage those nested values is to get the whole value and change the attribite you need and then pass it to your form:

const value = form.getFieldValue(field.key)
form.setFieldsValue({[field.key]: {...value, ['type']: your_new_value}})
like image 5
Sergei Klinov Avatar answered Oct 16 '22 15:10

Sergei Klinov