/* * @Description: 受控表单 */ import React, { useState, useEffect, useCallback, useRef, useImperativeHandle, ReactNode, Ref, } from 'react' import { Form, FormProps } from '../form' import { noop } from 'lodash' import { useForm, UseFormProps, FormInstance } from '../../common/hooks' import { getRecordPartialObject, isFalsy } from '../../common/utils' import { ControlledFormContext, ControlledFormContextProps } from './context' import { RecordPartial, StringKey, anyCallback } from '../../types' export interface ControlledFormProps extends UseFormProps, Omit { /* 表单实例,可拿到一些方法 */ form?: Ref> /* 要隐藏的表单项 */ hideItems?: RecordPartial /* 提交获取值是否过滤 null | undefined | '' */ isIgnoreFalsy?: boolean // 初始化是否触发onSubmit isSubmitInit?: boolean children?: ReactNode /* 表单提交的回调 */ onSubmit?(values: Partial): void } function ControlledForm(props: ControlledFormProps) { const { form, // 默认值 initialValues = getRecordPartialObject(), // 规格化配置 normalizes = getRecordPartialObject(), // 表单提交时是否去除值为undefined, null, ''的项 isIgnoreFalsy = true, isSubmitInit, // 隐藏的表单项 要隐藏将fieldName设为tue ,如{ alloc_type: true } hideItems = getRecordPartialObject(), children, // 表单项改变的时候,回调第一个是改变的字段及新的值,第二个参数是所有新的值 onFieldsChange = noop, // 表单提交的回调 onSubmit: onTempSubmit, ...res } = props const { values = getRecordPartialObject(), onChange, resetFields, setFieldsValue, getFieldsValue, getNormalizeValue, canSubmit, setCanSubmit, validateFields, } = useForm({ initialValues, normalizes, onFieldsChange, }) const [didClickSubmit, setDidClickSubmit] = useState(false) const didMountRef = useRef(false) const formRef = useRef
(null) // 表单提交 const onSubmit = useCallback((): void => { const tempValues: ControlledFormProps['initialValues'] = { ...values } if (isIgnoreFalsy || Object.keys(normalizes).length) { Object.keys(values).forEach((key) => { const tempKey = key as StringKey const value = values[tempKey] // 剔除掉undefined, null和空字符串 if (isIgnoreFalsy && isFalsy(value)) { delete tempValues[tempKey] } else { tempValues[tempKey] = getNormalizeValue(tempKey, value) } }) } setDidClickSubmit(true) onTempSubmit && canSubmit() && onTempSubmit(tempValues as K) }, [values, isIgnoreFalsy, normalizes, onTempSubmit, getNormalizeValue, canSubmit]) useEffect(() => { if (isSubmitInit && !didMountRef.current) { didMountRef.current = true onSubmit() } }, [isSubmitInit, onSubmit]) useImperativeHandle(form, () => ({ resetFields, setFieldsValue, getFieldsValue, validateFields: () => { setDidClickSubmit(true) return validateFields() }, apiDoValidate: () => { setDidClickSubmit(true) return canSubmit() }, })) const formProps = { ...res, ref: formRef, } if (onTempSubmit) { Object.assign(formProps, { onSubmit }) } const providerValues = { values, hideItems, onChange, resetFields, setFieldsValue, getFieldsValue, setCanSubmit, didClickSubmit, } as ControlledFormContextProps return ( {children} ) } export default ControlledForm