fix: fix display association fields with subform (#3036)

* fix: fix display association fields with subform

* fix: transformVariableValue

* fix: should also to request data when value is null

* fix: better way to fix
This commit is contained in:
被雨水过滤的空气-Rain 2023-11-14 14:15:47 +08:00 committed by GitHub
parent 887ddf0ed1
commit c25f51d99b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 19 deletions

View File

@ -7,6 +7,7 @@ import { useCollection, useCollectionManager } from '../../../../collection-mana
import { useFlag } from '../../../../flag-provider';
import { useVariables } from '../../../../variables';
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
import { isDisplayField, isFieldValueEmpty } from '../utils';
/**
* Form
@ -34,7 +35,8 @@ const useLazyLoadAssociationFieldOfForm = () => {
if (
isInAssignFieldValues ||
_.isEmpty(cloneRecord) ||
(formBlockType === 'create' && !isInSubForm && !isInSubTable)
(formBlockType === 'create' && !isInSubForm && !isInSubTable) ||
isDisplayField(schemaName)
) {
return;
}
@ -45,7 +47,7 @@ const useLazyLoadAssociationFieldOfForm = () => {
return;
}
if (!variables || record[schemaName] != null) {
if (!variables || !isFieldValueEmpty(_.get(record, schemaName))) {
return;
}
@ -67,7 +69,9 @@ const useLazyLoadAssociationFieldOfForm = () => {
// 3. 所以,当 `变量预加载` 的请求晚于编辑表单的请求时,就会造成这个问题;
// 更优的解决方案是:在 `变量预加载` 中也加上子表单中的关系字段路径,并删除编辑表单请求数据的逻辑(因为没必要了)。
// 但是这样改动较大,可以等之后 e2e 测试较完备后再处理。
if (field.value) return;
if (!isFieldValueEmpty(field.value)) {
return;
}
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
})

View File

@ -1,10 +1,14 @@
import { Field } from '@formily/core';
import { useField, useFieldSchema, useForm } from '@formily/react';
import { useEffect } from 'react';
import { nextTick } from '@nocobase/utils/client';
import _ from 'lodash';
import { useEffect, useRef } from 'react';
import { useCollection, useCollectionManager } from '../../../../collection-manager';
import { useFlag } from '../../../../flag-provider';
import { useVariables } from '../../../../variables';
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
import { useSubFormValue } from '../../association-field/hooks';
import { isDisplayField } from '../utils';
/**
* Form
@ -20,14 +24,29 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
const variables = useVariables();
const field = useField<Field>();
const { formValue: subFormValue } = useSubFormValue();
const { isInSubForm, isInSubTable } = useFlag() || {};
const schemaName = fieldSchema.name.toString();
const formValue = subFormValue || form.values;
const formValue = isInSubForm || isInSubTable ? subFormValue : form.values;
const collectionFieldRef = useRef(null);
if (collectionFieldRef.current == null) {
collectionFieldRef.current = getCollectionJoinField(`${name}.${schemaName}`);
}
const sourceKeyValue =
isDisplayField(schemaName) && collectionFieldRef.current
? _.get(formValue, `${schemaName.split('.')[0]}.${collectionFieldRef.current.sourceKey}`)
: undefined;
useEffect(() => {
// 如果 schemaName 中是以 `.` 分割的,说明是一个关联字段,需要去获取关联字段的值;
// 在数据表管理页面,也存在 `a.b` 之类的 schema name其 collectionName 为 fields所以在这里排除一下 `name === 'fields'` 的情况
if (!schemaName.includes('.') || !variables || name === 'fields') {
if (!isDisplayField(schemaName) || !variables || name === 'fields' || !collectionFieldRef.current) {
return;
}
if (_.isEmpty(formValue)) {
return;
}
@ -37,21 +56,23 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
collectionName: name,
};
const variableString = `{{ $nForm.${schemaName} }}`;
const collectionField = getCollectionJoinField(`${name}.${schemaName}`);
if (!collectionField) {
return console.error(new Error(`useLazyLoadAssociationField: ${schemaName} not found in collection ${name}`));
// 如果关系字段的 id 为空,则说明请求的数据还没有返回,此时还不能去解析变量
if (sourceKeyValue === undefined) {
return;
}
variables
.parseVariable(variableString, formVariable)
.then((value) => {
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
nextTick(() => {
field.value = transformVariableValue(value, { targetCollectionField: collectionFieldRef.current });
});
})
.catch((err) => {
console.error(err);
});
}, [schemaName.includes('.') ? formValue[schemaName.split('.')[0]] : null]);
}, [sourceKeyValue]);
};
export default useLazyLoadDisplayAssociationFieldsOfForm;

View File

@ -0,0 +1,10 @@
import _ from 'lodash';
export const isFieldValueEmpty = (value) => {
value = _.isArray(value) ? _.filter(value, (v) => !_.isEmpty(v)) : value;
return _.isEmpty(value);
};
export const isDisplayField = (schemaName: string) => {
return schemaName.includes('.');
};

View File

@ -277,13 +277,6 @@ VariablesProvider.displayName = 'VariablesProvider';
export default VariablesProvider;
/**
* null undefined
*
*
* @param value
* @returns
*/
function shouldToRequest(value) {
// fix https://nocobase.height.app/T-2502
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
@ -291,5 +284,5 @@ function shouldToRequest(value) {
return true;
}
return value === undefined;
return _.isEmpty(value);
}

View File

@ -103,4 +103,15 @@ describe('transformVariableValue', () => {
}
`);
});
test('value is undefined', () => {
const value = undefined;
const deps = {
targetCollectionField: { type: 'belongsToMany', uiSchema: { 'x-component': 'AssociationField' } },
};
const result = transformVariableValue(value, deps as any);
expect(result).toMatchInlineSnapshot(`undefined`);
});
});

View File

@ -14,6 +14,10 @@ interface Deps {
export const transformVariableValue = (value: any, deps: Deps) => {
const { targetCollectionField } = deps;
if (value == null) {
return value;
}
if (!targetCollectionField) {
return value;
}

View File

@ -41,3 +41,7 @@ export const hasEmptyValue = (objOrArr: object | any[]) => {
}
return result;
};
export const nextTick = (fn: () => void) => {
setTimeout(fn);
};