Search code examples
reactjsantd

Antd form value not received onFinish


I am developing an admin portal using Antd and this is something the I need in the design.

enter image description here

I managed to develop the design using the following code

<Form
labelWrap
wrapperCol={{ span: 24 }}
initialValues={detail && detail.object}
onFinish={handleEdit}>
<Row gutter={100}>
    <Col span={12}>
        <Item
            labelCol={{ span: 7 }}
            label='Status'
            name='status'
            valuePropName='checked'
            required>
            <Space> //-----------#1
                <p className='text-green'>Active</p> //--------#2
                <Switch defaultChecked={detail && detail.object.status} />
                <p className='text-red'>Inactive</p> //------------#3
            </Space> //---------#4
        </Item>
    </Col>
</Row>
</Form>

But when I try to handle the submit function, I am not getting the value of the switch element. I comes as undefined.

const handleEdit = async (values) => {
    console.log(values);
};

But I get the status value correctly when the Switch component is the immediate child of the Item by removing commented lines #1, #2, #3, #4.

I tried using the form.getFieldsValue() method. But that also didn't help.

Is there any way I can get the value in the desired way?


Solution

  • When you pass name prop to Form.Item, the first child of Form.Item is controlled by Form.Item. Since Switch is not the first child of Form.Item, it is not controlled by Form.Item and you didn't get the value status. There are two possible solutions:

    Solution 1: Use Form.Item with noStyle prop to design the layout (You can follow this example Complex form control)

    Solution 2: Create a custom component that will receives value & onChange prop. Example

    import { Col, Form, Row, Space, Switch } from 'antd';
    
    const { Item } = Form;
    
    const CustomSwitch = ({ value, onChange }) => {
        return (
            <Space>
                <p className='text-green'>Active</p>
                <Switch value={value} onChange={onChange} />
                <p className='text-red'>Inactive</p>
            </Space>
        );
    };
    
    const App = () => {
        return (
            <Form labelWrap wrapperCol={{ span: 24 }}>
                <Row gutter={100}>
                    <Col span={12}>
                        {/* Solution 1 */}
                        <Item labelCol={{ span: 7 }} label='Status'>
                            <Space>
                                <p className='text-green'>Active</p>
                                <Item name='status' noStyle valuePropName='checked' required>
                                    <Switch />
                                </Item>
                                <p className='text-red'>Inactive</p>
                            </Space>
                        </Item>
    
                        {/* Solution 2 */}
                        <Item labelCol={{ span: 7 }} label='Status' name='status' valuePropName='checked' required>
                            <CustomSwitch />
                        </Item>
                    </Col>
                </Row>
            </Form>
        );
    };
    
    export default App;