Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/components/form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const Form = forwardRefWithStatics(
const formRef = useRef<HTMLFormElement>(null);
const formMapRef = useRef(new Map()); // 收集所有包含 name 属性 formItem 实例
const floatingFormDataRef = useRef({}); // 储存游离值的 formData
const formInstance = useInstance(props, formRef, formMapRef, floatingFormDataRef);
const formInstance = useInstance(props, formRef, formMapRef, floatingFormDataRef, form);

useImperativeHandle(ref, () => formInstance);
Object.assign(form, { ...formInstance });
Expand All @@ -71,6 +71,7 @@ const Form = forwardRefWithStatics(
});
form?.getInternalHooks?.(HOOK_MARK)?.notifyWatch?.([]);
form.store = {};
floatingFormDataRef.current = {};
onReset?.({ e });
}

Expand Down
5 changes: 4 additions & 1 deletion packages/components/form/hooks/interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NamePath, FormInstanceFunctions } from '../type';
import type { FormInstanceFunctions, NamePath } from '../type';

export type Store = Record<string, any>;

Expand All @@ -13,6 +13,9 @@ export interface InternalHooks {
setForm: (form) => void;
}

/**
* @internal
*/
export interface InternalFormInstance extends FormInstanceFunctions {
_init?: boolean;
store?: Store;
Expand Down
4 changes: 2 additions & 2 deletions packages/components/form/hooks/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useRef } from 'react';
import log from '@tdesign/common-js/log/index';
import type { NamePath } from '../type';
import type { FormInstanceFunctions, NamePath } from '../type';
import type { WatchCallBack, InternalHooks, InternalFormInstance, Store } from './interface';

export const HOOK_MARK = 'TD_FORM_INTERNAL_HOOKS';
Expand Down Expand Up @@ -102,7 +102,7 @@ class FormStore {
};
}

export default function useForm(form?: InternalFormInstance) {
export default function useForm(form?: FormInstanceFunctions) {
const formRef = useRef<InternalFormInstance>(Object.create({}));
const [, forceUpdate] = useState({});

Expand Down
29 changes: 24 additions & 5 deletions packages/components/form/hooks/useInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
NamePath,
TdFormProps,
} from '../type';
import type { InternalFormInstance } from './interface';

// 检测是否需要校验 默认全量校验
function needValidate(name: NamePath, fields: string[]) {
Expand Down Expand Up @@ -44,7 +45,8 @@ export default function useInstance(
props: TdFormProps,
formRef: React.RefObject<HTMLFormElement>,
formMapRef: React.MutableRefObject<Map<any, any>>,
floatingFormDataRef: React.RefObject<Record<any, any>>,
floatingFormDataRef: React.MutableRefObject<Record<any, any>>,
form: InternalFormInstance,
) {
const { classPrefix } = useConfig();

Expand Down Expand Up @@ -111,7 +113,10 @@ export default function useInstance(
function getFieldValue(name: NamePath) {
if (!name) return null;
const formItemRef = findFormItem(name, formMapRef);
return formItemRef?.current?.getValue?.();
if (formItemRef?.current) {
return formItemRef.current.getValue?.();
}
return get(floatingFormDataRef.current, name);
}

// 对外方法,获取一组字段名对应的值,当调用 getFieldsValue(true) 时返回所有值
Expand All @@ -133,6 +138,8 @@ export default function useInstance(
const [name, formItemRef] = entries[i];
processField(name, formItemRef);
}
// 即使没有对应的 FormItem 渲染,也返回数据,用于支持动态 set 的场景
merge(fieldsValue, cloneDeep(floatingFormDataRef.current));
} else {
if (!Array.isArray(nameList)) {
log.error('Form', 'The parameter of "getFieldsValue" must be an array');
Expand All @@ -141,13 +148,21 @@ export default function useInstance(
for (let i = 0; i < nameList.length; i++) {
const name = nameList[i];
const formItemRef = findFormItem(name, formMapRef);
processField(name, formItemRef);
if (formItemRef?.current) {
processField(name, formItemRef);
} else {
const floatingValue = get(floatingFormDataRef.current, name);
const fieldValue = calcFieldValue(name, floatingValue, !props.supportNumberKey);
merge(fieldsValue, fieldValue);
}
}
}
return cloneDeep(fieldsValue);
}

// 对外方法,设置对应 formItem 的值
/**
* 对外方法,设置对应 FormItem 的值
*/
function setFieldsValue(fields = {}) {
const nameLists = objectToArray(fields);
nameLists.forEach((nameList) => {
Expand All @@ -157,11 +172,15 @@ export default function useInstance(
formItemRef.current.setValue?.(fieldValue);
} else {
set(floatingFormDataRef.current, nameList, fieldValue);
// 确保 store 始终包含所有被 set 的字段
set(form?.store, nameList, fieldValue);
}
});
}

// 对外方法,设置对应 formItem 的数据
/**
* 对外方法,设置对应 FormItem 的状态
*/
function setFields(fields = []) {
if (!Array.isArray(fields)) throw new TypeError('The parameter of "setFields" must be an array');

Expand Down
Loading