1- import { flattenDeep , get , isEqual , isFunction , isObject , isString , merge , set , unset } from 'lodash-es' ;
21import React , { forwardRef , ReactNode , useEffect , useImperativeHandle , useMemo , useRef , useState } from 'react' ;
32import {
43 CheckCircleFilledIcon as TdCheckCircleFilledIcon ,
54 CloseCircleFilledIcon as TdCloseCircleFilledIcon ,
65 ErrorCircleFilledIcon as TdErrorCircleFilledIcon ,
76} from 'tdesign-icons-react' ;
7+ import { get , isEqual , isFunction , isObject , isString , set , unset } from 'lodash-es' ;
8+
89import useConfig from '../hooks/useConfig' ;
910import useDefaultProps from '../hooks/useDefaultProps' ;
1011import useGlobalIcon from '../hooks/useGlobalIcon' ;
1112import { useLocaleReceiver } from '../locale/LocalReceiver' ;
12- import { ValidateStatus } from './const' ;
13+ import { READONLY_SUPPORTED_COMP , ValidateStatus } from './const' ;
1314import { formItemDefaultProps } from './defaultProps' ;
1415import { useFormContext , useFormListContext } from './FormContext' ;
1516import { parseMessage , validate as validateModal } from './formModel' ;
1617import { HOOK_MARK } from './hooks/useForm' ;
1718import useFormItemInitialData , { ctrlKeyMap } from './hooks/useFormItemInitialData' ;
1819import useFormItemStyle from './hooks/useFormItemStyle' ;
19- import { calcFieldValue } from './utils' ;
20+ import { calcFieldValue , concatName } from './utils' ;
2021
2122import type { StyledProps } from '../common' ;
2223import type {
@@ -37,13 +38,14 @@ export interface FormItemProps extends TdFormItemProps, StyledProps {
3738
3839export interface FormItemInstance {
3940 name ?: NamePath ;
41+ fullPath ?: NamePath [ ] ;
4042 value ?: any ;
41- isUpdated ?: boolean ;
43+ initialData ?: any ;
4244 isFormList ?: boolean ;
4345 formListMapRef ?: React . MutableRefObject < Map < any , any > > ;
4446 getValue ?: ( ) => any ;
45- setValue ?: ( newVal : any , originalData ?: any ) => void ;
46- setField ?: ( field : Omit < FieldData , 'name' > , originalData ?: any ) => void ;
47+ setValue ?: ( newVal : any ) => void ;
48+ setField ?: ( field : Omit < FieldData , 'name' > ) => void ;
4749 validate ?: ( trigger ?: ValidateTriggerType , showErrorMessage ?: boolean ) => Promise < Record < string , any > > ;
4850 validateOnly ?: ( trigger ?: ValidateTriggerType ) => Promise < Record < string , any > > ;
4951 resetField ?: ( type ?: TdFormProps [ 'resetType' ] ) => void ;
@@ -102,7 +104,10 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
102104 requiredMark = requiredMarkFromContext ,
103105 } = props ;
104106
105- const { getDefaultInitialData } = useFormItemInitialData ( name ) ;
107+ const { fullPath : parentFullPath } = useFormListContext ( ) ;
108+ const fullPath = concatName ( parentFullPath , name ) ;
109+
110+ const { getDefaultInitialData } = useFormItemInitialData ( name , fullPath ) ;
106111
107112 const [ , forceUpdate ] = useState ( { } ) ; // custom render state
108113 const [ freeShowErrorMessage , setFreeShowErrorMessage ] = useState ( undefined ) ;
@@ -111,22 +116,16 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
111116 const [ verifyStatus , setVerifyStatus ] = useState ( 'validating' ) ;
112117 const [ resetValidating , setResetValidating ] = useState ( false ) ;
113118 const [ needResetField , setNeedResetField ] = useState ( false ) ;
114- const [ formValue , setFormValue ] = useState ( ( ) => {
115- const fieldName = flattenDeep ( [ formListName , name ] ) ;
116- const storeValue = get ( form ?. store , fieldName ) ;
117- return (
118- storeValue ??
119- getDefaultInitialData ( {
120- children,
121- initialData,
122- } )
123- ) ;
124- } ) ;
119+ const [ formValue , setFormValue ] = useState ( ( ) =>
120+ getDefaultInitialData ( {
121+ children,
122+ initialData,
123+ } ) ,
124+ ) ;
125125
126126 const formItemRef = useRef < FormItemInstance > ( null ) ; // 当前 formItem 实例
127127 const innerFormItemsRef = useRef ( [ ] ) ;
128128 const shouldEmitChangeRef = useRef ( false ) ; // onChange 冒泡开关
129- const isUpdatedRef = useRef ( false ) ; // 校验开关
130129 const shouldValidate = useRef ( false ) ; // 校验开关
131130 const valueRef = useRef ( formValue ) ; // 当前最新值
132131 const errorListMapRef = useRef ( new Map ( ) ) ;
@@ -171,22 +170,11 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
171170 const { setPrevStore } = form ?. getInternalHooks ?.( HOOK_MARK ) || { } ;
172171 setPrevStore ?.( form ?. getFieldsValue ?.( true ) ) ;
173172 shouldEmitChangeRef . current = shouldEmitChange ;
174- isUpdatedRef . current = true ;
175173 shouldValidate . current = validate ;
176174 valueRef . current = newVal ;
177-
178- let fieldName = [ ] . concat ( name ) ;
179- let fieldValue = formValue ;
180- if ( formListName ) {
181- fieldName = [ ] . concat ( formListName , name ) ;
182- fieldValue = get ( form ?. store , fieldName ) ;
183- }
184-
185- fieldName = fieldName . filter ( ( item ) => item !== undefined ) ;
186-
187- if ( ! fieldName ) return ;
175+ const fieldValue = get ( form ?. store , fullPath ) ;
188176 if ( isEqual ( fieldValue , newVal ) ) return ;
189- set ( form ?. store , fieldName , newVal ) ;
177+ set ( form ?. store , fullPath , newVal ) ;
190178 setFormValue ( newVal ) ;
191179 } ;
192180
@@ -332,7 +320,6 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
332320 // blur 下触发校验
333321 function handleItemBlur ( ) {
334322 const filterRules = innerRules . filter ( ( item ) => item . trigger === 'blur' ) ;
335-
336323 filterRules . length && validate ( 'blur' ) ;
337324 }
338325
@@ -429,21 +416,23 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
429416 // 记录填写 name 属性 formItem
430417 if ( typeof name === 'undefined' ) return ;
431418
432- // formList 下特殊处理
419+ // FormList 下特殊处理
433420 if ( formListName && isSameForm ) {
434- formListMapRef . current . set ( name , formItemRef ) ;
421+ formListMapRef . current . set ( fullPath , formItemRef ) ;
422+ set ( form ?. store , fullPath , formValue ) ;
435423 return ( ) => {
436424 // eslint-disable-next-line react-hooks/exhaustive-deps
437- formListMapRef . current . delete ( name ) ;
438- unset ( form ?. store , name ) ;
425+ formListMapRef . current . delete ( fullPath ) ;
426+ unset ( form ?. store , fullPath ) ;
439427 } ;
440428 }
441429 if ( ! formMapRef ) return ;
442- formMapRef . current . set ( name , formItemRef ) ;
430+ formMapRef . current . set ( fullPath , formItemRef ) ;
431+ set ( form ?. store , fullPath , formValue ) ;
443432 return ( ) => {
444433 // eslint-disable-next-line react-hooks/exhaustive-deps
445- formMapRef . current . delete ( name ) ;
446- unset ( form ?. store , name ) ;
434+ formMapRef . current . delete ( fullPath ) ;
435+ unset ( form ?. store , fullPath ) ;
447436 } ;
448437 // eslint-disable-next-line react-hooks/exhaustive-deps
449438 } , [ snakeName , formListName ] ) ;
@@ -455,18 +444,9 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
455444 // 控制是否需要校验
456445 if ( ! shouldValidate . current ) return ;
457446
458- // value change event
459447 if ( typeof name !== 'undefined' && shouldEmitChangeRef . current ) {
460- if ( formListName && isSameForm ) {
461- // 整理 formItem 的值
462- const formListValue = merge ( [ ] , calcFieldValue ( name , formValue ) ) ;
463- // 整理 formList 的值
464- const fieldValue = calcFieldValue ( formListName , formListValue ) ;
465- onFormItemValueChange ?.( { ...fieldValue } ) ;
466- } else {
467- const fieldValue = calcFieldValue ( name , formValue ) ;
468- onFormItemValueChange ?.( { ...fieldValue } ) ;
469- }
448+ const fieldValue = calcFieldValue ( fullPath , formValue ) ;
449+ onFormItemValueChange ?.( fieldValue ) ;
470450 }
471451
472452 const filterRules = innerRules . filter ( ( item ) => ( item . trigger || 'change' ) === 'change' ) ;
@@ -478,8 +458,10 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
478458 // 暴露 ref 实例方法
479459 const instance : FormItemInstance = {
480460 name,
461+ fullPath,
481462 value : formValue ,
482- isUpdated : isUpdatedRef . current ,
463+ initialData,
464+ isFormList : false ,
483465 getValue : ( ) => valueRef . current ,
484466 setValue : ( newVal : any ) => updateFormValue ( newVal , true , true ) ,
485467 setField,
@@ -524,9 +506,11 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
524506 ctrlKey = ctrlKeyMap . get ( child . type ) || 'value' ;
525507 }
526508 const childProps = child . props as any ;
509+ // @ts -ignore
510+ const readOnlyKey = READONLY_SUPPORTED_COMP . includes ( child ?. type ?. displayName ) ? 'readonly' : 'readOnly' ;
527511 return React . cloneElement ( child , {
528512 disabled : disabledFromContext ,
529- readOnly : readonlyFromContext ,
513+ [ readOnlyKey ] : readonlyFromContext ,
530514 ...childProps ,
531515 [ ctrlKey ] : formValue ,
532516 onChange : ( value : any , ...args : any [ ] ) => {
0 commit comments