溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

antd?form表單怎么處理自定義組件

發(fā)布時(shí)間:2023-04-21 11:31:41 來源:億速云 閱讀:97 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下antd form表單怎么處理自定義組件的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    antd form表單處理自定義組件

    使用 antd 中的 Form 組件時(shí),若使用自定義組件時(shí),保存的時(shí)候獲取不到自定義組件中的值。

    以下是從antd找到的解決思路

    被設(shè)置了 name 屬性的 Form.Item 包裝的控件,表單控件會(huì)自動(dòng)添加 value(或 valuePropName 指定的其他屬性) onChange(或 trigger 指定的其他屬性)

    我們可以通過表單控件自動(dòng)添加的onChage,來做數(shù)據(jù)收集同步。

    父組件:

    import React, { Fragment, useState, useEffect, forwardRef, useRef } from 'react';
    import HeaderTable from './headerTable';
    
    const BasicForm = forwardRef((props, ref) => {
      const { record } = props;
      const [ form ] = Form.useForm();
    
        <Form
              name="taskForm"
              ref={ref}
              form={form}
            >
            <Row gutter={20}>
                <Col span={24}>
                  <Form.Item  name="headers" label={'Header'}>
                    <HeaderTable ref={headerTableRef} record={record} />
                  </Form.Item>
                </Col>
              </Row>
        </Form>
    export default BasicForm;

    子組件:

    import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef} from 'react';
    import { Transfer, Divider, Table, Button, Input, message, Select } from 'antd';
    import AddRowTable from '@components/AddRowTable';//Table組件
    
    const { Option } = Select;
    
    const DATATYPE = [
        {
            id: 1,
            name: 'int'
        }, {
            id: 2,
            name: 'varchar'
        }
    ]
    
    const HeaderTable = ( props, ref ) => {
        const { record, isLook, onChange } = props;
        const addRowTable = useRef();
        const [ sourceData, setSourceData ] = useState([]);
        const [ columns, setColumns ] = useState([]);
        const [ targetKeys, setTargetKeys ] = useState([]);
        const [ headerList, setHeaderList ] = useState([]);
    
        useEffect(() => {
            if (record && record.id) {//當(dāng)編輯時(shí)將傳來的數(shù)據(jù)賦值
                setHeaderList(record.sourceInfoMap.headers)
            }
        }, [record])
            
            //設(shè)置columns表頭
            useEffect(() => {
            const columns = [
        {
                title: '參數(shù)名稱',
                dataIndex: 'name',
                render: (text, record) => {
            return (
                <Input value={text} onChange={tableItemChange.bind(this, record, 'name')} />
                );
            }
        },
            {
                title: '操作',
                dataIndex: 'operation',
                align: 'center',
                render: (text, record, index) => {
            return (
                        <a onClick={delHandle.bind(this, record, index)}>'Delete'</a>
                            );
            }
        }];
            
            setColumns(columns);
            
            },[])
    
        // 添加一行
        const handleAddTableRow = () => {
            setHeaderList(headerList => [...headerList, {}]);
            onChange(headerList => [...headerList, {}])
        };
    
    
        // 刪除一行
        const delHandle = (record, index) => {
            setHeaderList(headerList => {
                headerList.splice(index, 1);
                onChange(headerList)
                return [...headerList];
            });
        };
    
        // 表格中數(shù)據(jù)更改
        const tableItemChange = (data, keyField, evt) => {
            const value = evt.target ? evt.target.value : evt;
            data[keyField] = value;
            onChange(headerList)
        };
    
        return <div>
            <AddRowTable
                ref={addRowTable}
                dataSource={headerList}
                columns={columns}
                isCanAdd={isLook}
          disabled={isLook}
                addItem={handleAddTableRow.bind(this)}
            />
        </div>
    }
    
    export default HeaderTable;

    以上操作就可以在表單中使用自定義組件,表單也能統(tǒng)一獲取值。

    不僅僅input輸入框可以這么操作,所有組件,只要你拿到值后,把值給 onChange 方法,都是可以統(tǒng)一獲取值的。

    antd form表單中嵌套自定義組件

    當(dāng)某些自定義的組合類組件,也希望能進(jìn)行表單元素的校驗(yàn),以及利用antd的form表單實(shí)例進(jìn)行數(shù)據(jù)的修改或者數(shù)據(jù)獲取,這招便可以派上用場啦~

    表單部分

    <Form.Item label="周期" labelAlign="right">
        {getFieldDecorator('cycle', {
            rules: [{ required: true, validator: checkCycle }],
            initialValue: cycle,
        })(<CycleInput cycleOptions={cycleOptions} />)}
    </Form.Item>

    表單部分可以引入自定義的校驗(yàn)邏輯,如上面的checkCycle :

    可以像下面這樣,通過Promise.reject()返回錯(cuò)誤校驗(yàn)提示,通過Promise.resolve()正確通過校驗(yàn)。

    /** 校驗(yàn)生命周期輸入內(nèi)容 */
    const checkCycle = useCallback((_, value) => {
         const format = value?.split(' ');
         if (!format) return Promise.reject(new Error('周期不可為空!'));
    
         /** always 永久保存選項(xiàng) */
         if (format.length < 2 && format[0] === 'always') {
             return Promise.resolve();
         }
         if (format[1] === 'undefined') {
             return Promise.reject(new Error('請(qǐng)選擇周期!'));
         }
         const num = +format[0];
         if (num > 0 && format[1]) {
             return Promise.resolve();
         }
         return Promise.reject(new Error('請(qǐng)輸入大于 0 的數(shù)字!'));
     }, []);

    有關(guān)校驗(yàn)的內(nèi)容,antd也是參考一個(gè)成熟的庫 async-validator,上面這種寫法可以參考文檔這塊 asyncValidator

    如果懶得看文檔直接看圖:

    antd?form表單怎么處理自定義組件

    大概意思就是說,可以通過兩種方式來實(shí)現(xiàn)一些異步校驗(yàn):

    (1)可以通過調(diào)用callback,即asyncValidator的第三個(gè)參數(shù),來完成校驗(yàn)

    (2)可以通過返回Promise,來完成校驗(yàn)

    自定義組件

    注意value是該表單域的值,onChange是對(duì)應(yīng)可以改變?cè)摫韱斡虻闹档姆椒?/p>

    const CycleInput = ({ value, onChange, cycleOptions }) => {
        const format = value?.split?.(' ');
        const num = format?.[0];
        const type = format?.[1];
    
        const triggerChange = changedValue => {
            onChange && onChange(changedValue);
        };
    
        /** 根據(jù)后端接口返回的數(shù)據(jù),type 有值,則為 day、week、month、year 其一 */
        /** type 若為 undefined,則 num 為 always */
        const [cycleOption, setCycleOption] = useState(type ?? num);
        const [cycleInputValue, setCycleInputValue] = useState(
            (typeof +num === 'number' && !_.isNaN(+num) && num) || '',
        );
    
        const onCycleChange = cycleOption => {
            setCycleOption(cycleOption);
            triggerChange(
                cycleOption === 'always'
                    ? cycleOption
                    : `${cycleInputValue} ${cycleOption}`,
            );
        };
    
        const onInputChange = e => {
            const newNumber = parseInt(e.target.value || '0', 10);
            if (_.isNaN(newNumber)) {
                return;
            }
            setCycleInputValue(newNumber);
            triggerChange(
                cycleOption === 'always' ? cycleOption : `${newNumber} ${cycleOption}`,
            );
        };
    
        return (
            <Input.Group>
                {cycleOption === 'always' ? (
                    <Select
                        onChange={onCycleChange }
                        defaultValue={cycleOption}
                        style={{ width: 240 }}
                    >
                        {cycleOptions.map(item => (
                            <Select.Option key={item.value} value={item.value}>
                                {item.label}
                            </Select.Option>
                        ))}
                    </Select>
                ) : (
                    <span>
                        <Input
                            value={cycleInputValue}
                            style={{ width: 156 }}
                            onChange={onInputChange}
                        />
                        <Select
                            onChange={onCycleChange}
                            defaultValue={cycleOption}
                            style={{ width: 84 }}
                        >
                            {cycleOptions.map(item => (
                                <Select.Option key={item.value} value={item.value}>
                                    {item.label}
                                </Select.Option>
                            ))}
                        </Select>
                    </span>
                )}
            </Input.Group>
        );
    };

    可以看出,自定義部分邏輯也比較簡單,通過value參數(shù)可以展示組件的值,通過onChange方法,可以改變表單域的值,實(shí)現(xiàn)了表單帶給我們的便捷功能。

    以上就是“antd form表單怎么處理自定義組件”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI