From dc4754750d916dcae87995682baf23684a64b36a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?=
=?UTF-8?q?=E7=A9=BA=E6=B0=94-Rain?= <958414905@qq.com>
Date: Sat, 21 Oct 2023 10:19:34 +0800
Subject: [PATCH] fix(variable): fix currentObject (#2887)
* fix(variable): fix currentObject
* refactor: rename
---
.../antd/association-field/Nester.tsx | 46 ++++++++--------
.../antd/association-field/hooks.ts | 53 +++++++++++++------
.../form-item/hooks/useParseDefaultValue.ts | 5 +-
.../schema-component/antd/table-v2/Table.tsx | 29 +++++-----
4 files changed, 82 insertions(+), 51 deletions(-)
diff --git a/packages/core/client/src/schema-component/antd/association-field/Nester.tsx b/packages/core/client/src/schema-component/antd/association-field/Nester.tsx
index 8c85bfe86..d32951028 100644
--- a/packages/core/client/src/schema-component/antd/association-field/Nester.tsx
+++ b/packages/core/client/src/schema-component/antd/association-field/Nester.tsx
@@ -19,7 +19,7 @@ import {
} from '../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
import { LocalVariablesProvider } from '../../../variables/hooks/useLocalVariables';
import { AssociationFieldContext } from './context';
-import { useAssociationFieldContext } from './hooks';
+import { SubFormProvider, useAssociationFieldContext } from './hooks';
export const Nester = (props) => {
const { options } = useContext(AssociationFieldContext);
@@ -78,13 +78,15 @@ const ToOneNester = (props) => {
return (
-
-
-
- {props.children}
-
-
-
+
+
+
+
+ {props.children}
+
+
+
+
);
};
@@ -186,19 +188,21 @@ const ToManyNester = observer(
)}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/core/client/src/schema-component/antd/association-field/hooks.ts b/packages/core/client/src/schema-component/antd/association-field/hooks.ts
index 40fff237c..2296ae9fe 100644
--- a/packages/core/client/src/schema-component/antd/association-field/hooks.ts
+++ b/packages/core/client/src/schema-component/antd/association-field/hooks.ts
@@ -1,10 +1,10 @@
import { GeneralField } from '@formily/core';
import { useField, useFieldSchema } from '@formily/react';
import { reaction } from '@formily/reactive';
-import { flatten } from '@nocobase/utils/client';
+import { flatten, getValuesByPath } from '@nocobase/utils/client';
import _, { isString } from 'lodash';
import cloneDeep from 'lodash/cloneDeep';
-import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useFormBlockContext } from '../../../block-provider';
import { mergeFilter } from '../../../block-provider/SharedFilterProvider';
import { useCollection, useCollectionManager } from '../../../collection-manager';
@@ -58,6 +58,7 @@ export default function useServiceOptions(props) {
const { parseFilter } = useParseDataScopeFilter();
const [fieldServiceFilter, setFieldServiceFilter] = useState(null);
const { form } = useFormBlockContext();
+ const { formValue: subFormValue } = useSubFormValue();
useEffect(() => {
const filterFromSchema = isString(fieldSchema?.['x-component-props']?.service?.params?.filter)
@@ -72,7 +73,7 @@ export default function useServiceOptions(props) {
_run();
- reaction(() => {
+ const dispose = reaction(() => {
// 这一步主要是为了使 reaction 能够收集到依赖
const flat = flatten(filterFromSchema, {
breakOn({ key }) {
@@ -82,16 +83,28 @@ export default function useServiceOptions(props) {
if (!isVariable(value)) {
return value;
}
- const result = _.get({ $nForm: form?.values }, getPath(value));
+ const result = getValuesByPath(
+ {
+ $nForm: form?.values,
+ $iteration: subFormValue,
+ },
+ getPath(value),
+ );
return result;
},
});
return flat;
}, run);
+
+ return dispose;
}, [
field.componentProps?.service?.params?.filter,
- fieldSchema?.['x-component-props']?.service?.params?.filter,
+ fieldSchema,
+ form?.values,
+ parseFilter,
+ record,
service?.params?.filter,
+ subFormValue,
]);
const normalizeValues = useCallback(
@@ -160,16 +173,7 @@ export default function useServiceOptions(props) {
],
'$or',
);
- }, [
- collectionField?.interface,
- collectionField?.foreignKey,
- fieldSchema,
- fieldServiceFilter,
- sourceValue,
- params?.filter,
- value,
- fieldNames?.value,
- ]);
+ }, [collectionField?.interface, collectionField.foreignKey, fieldSchema, fieldServiceFilter, sourceValue]);
return useMemo(() => {
return {
@@ -189,3 +193,22 @@ export const useFieldNames = (props) => {
props.fieldNames;
return { label: 'label', value: 'value', ...fieldNames };
};
+
+const SubFormContext = createContext>(null);
+export const SubFormProvider = SubFormContext.Provider;
+
+/**
+ * 用于获取子表单所对应的 form 对象,其应该保持响应性,即一个 Proxy 对象;
+ *
+ * ## 为什么要有这个方法?
+ * 1. 目前使用 useForm 方法获取到的是普通表单区块的 form 对象,无法通过简单的方法获取到子表单对应的 form 对象;
+ * 2. 虽然现在 useRecord 也可以获取到相同值的对象,但是这个对象不是响应式的(因其内部 copy 过一次),字段值变更时无法监听到;
+ * 3. 可能更好的方式是在 useForm 返回的 form 对象添加一个 parent 属性,但可能会影响其它部分的代码,所以暂时不做修改;
+ * @returns
+ */
+export const useSubFormValue = () => {
+ const context = useContext(SubFormContext);
+ return {
+ formValue: context,
+ };
+};
diff --git a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
index c84da9bcf..33d3c9499 100644
--- a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
+++ b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
@@ -1,6 +1,7 @@
import { Field } from '@formily/core';
import { useField, useFieldSchema } from '@formily/react';
import { reaction } from '@formily/reactive';
+import { getValuesByPath } from '@nocobase/utils/client';
import _ from 'lodash';
import { useEffect } from 'react';
import { useRecord, useRecordIndex } from '../../../../../src/record-provider';
@@ -102,12 +103,12 @@ const useParseDefaultValue = () => {
const path = getPath(fieldSchema.default);
// fix https://nocobase.height.app/T-2212
- if (_.get(obj, path) === undefined) {
+ if (getValuesByPath(obj, path) === undefined) {
// 返回一个随机值,确保能触发 run 函数
return Math.random();
}
- return _.get(obj, path);
+ return getValuesByPath(obj, path);
}, run);
return dispose;
diff --git a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
index ed41f61c6..5ef064adb 100644
--- a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
+++ b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
@@ -24,6 +24,7 @@ import {
import { useACLFieldWhitelist } from '../../../acl/ACLProvider';
import { LocalVariablesProvider } from '../../../variables/hooks/useLocalVariables';
import { useToken } from '../__builtins__';
+import { SubFormProvider } from '../association-field/hooks';
import { ColumnFieldProvider } from './components/ColumnFieldProvider';
import { extractIndex, isCollectionFieldComponent, isColumnComponent } from './utils';
@@ -62,19 +63,21 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
render: (v, record) => {
const index = field.value?.indexOf(record);
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
},
} as TableColumnProps;