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:
parent
887ddf0ed1
commit
c25f51d99b
@ -7,6 +7,7 @@ import { useCollection, useCollectionManager } from '../../../../collection-mana
|
|||||||
import { useFlag } from '../../../../flag-provider';
|
import { useFlag } from '../../../../flag-provider';
|
||||||
import { useVariables } from '../../../../variables';
|
import { useVariables } from '../../../../variables';
|
||||||
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
|
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
|
||||||
|
import { isDisplayField, isFieldValueEmpty } from '../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于懒加载 Form 区块中正常的关系字段
|
* 用于懒加载 Form 区块中正常的关系字段
|
||||||
@ -34,7 +35,8 @@ const useLazyLoadAssociationFieldOfForm = () => {
|
|||||||
if (
|
if (
|
||||||
isInAssignFieldValues ||
|
isInAssignFieldValues ||
|
||||||
_.isEmpty(cloneRecord) ||
|
_.isEmpty(cloneRecord) ||
|
||||||
(formBlockType === 'create' && !isInSubForm && !isInSubTable)
|
(formBlockType === 'create' && !isInSubForm && !isInSubTable) ||
|
||||||
|
isDisplayField(schemaName)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -45,7 +47,7 @@ const useLazyLoadAssociationFieldOfForm = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!variables || record[schemaName] != null) {
|
if (!variables || !isFieldValueEmpty(_.get(record, schemaName))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +69,9 @@ const useLazyLoadAssociationFieldOfForm = () => {
|
|||||||
// 3. 所以,当 `变量预加载` 的请求晚于编辑表单的请求时,就会造成这个问题;
|
// 3. 所以,当 `变量预加载` 的请求晚于编辑表单的请求时,就会造成这个问题;
|
||||||
// 更优的解决方案是:在 `变量预加载` 中也加上子表单中的关系字段路径,并删除编辑表单请求数据的逻辑(因为没必要了)。
|
// 更优的解决方案是:在 `变量预加载` 中也加上子表单中的关系字段路径,并删除编辑表单请求数据的逻辑(因为没必要了)。
|
||||||
// 但是这样改动较大,可以等之后 e2e 测试较完备后再处理。
|
// 但是这样改动较大,可以等之后 e2e 测试较完备后再处理。
|
||||||
if (field.value) return;
|
if (!isFieldValueEmpty(field.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
|
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import { Field } from '@formily/core';
|
import { Field } from '@formily/core';
|
||||||
import { useField, useFieldSchema, useForm } from '@formily/react';
|
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 { useCollection, useCollectionManager } from '../../../../collection-manager';
|
||||||
|
import { useFlag } from '../../../../flag-provider';
|
||||||
import { useVariables } from '../../../../variables';
|
import { useVariables } from '../../../../variables';
|
||||||
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
|
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
|
||||||
import { useSubFormValue } from '../../association-field/hooks';
|
import { useSubFormValue } from '../../association-field/hooks';
|
||||||
|
import { isDisplayField } from '../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于懒加载 Form 区块中只用于展示的关联字段的值
|
* 用于懒加载 Form 区块中只用于展示的关联字段的值
|
||||||
@ -20,14 +24,29 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
|
|||||||
const variables = useVariables();
|
const variables = useVariables();
|
||||||
const field = useField<Field>();
|
const field = useField<Field>();
|
||||||
const { formValue: subFormValue } = useSubFormValue();
|
const { formValue: subFormValue } = useSubFormValue();
|
||||||
|
const { isInSubForm, isInSubTable } = useFlag() || {};
|
||||||
|
|
||||||
const schemaName = fieldSchema.name.toString();
|
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(() => {
|
useEffect(() => {
|
||||||
// 如果 schemaName 中是以 `.` 分割的,说明是一个关联字段,需要去获取关联字段的值;
|
// 如果 schemaName 中是以 `.` 分割的,说明是一个关联字段,需要去获取关联字段的值;
|
||||||
// 在数据表管理页面,也存在 `a.b` 之类的 schema name,其 collectionName 为 fields,所以在这里排除一下 `name === 'fields'` 的情况
|
// 在数据表管理页面,也存在 `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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,21 +56,23 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
|
|||||||
collectionName: name,
|
collectionName: name,
|
||||||
};
|
};
|
||||||
const variableString = `{{ $nForm.${schemaName} }}`;
|
const variableString = `{{ $nForm.${schemaName} }}`;
|
||||||
const collectionField = getCollectionJoinField(`${name}.${schemaName}`);
|
|
||||||
|
|
||||||
if (!collectionField) {
|
// 如果关系字段的 id 为空,则说明请求的数据还没有返回,此时还不能去解析变量
|
||||||
return console.error(new Error(`useLazyLoadAssociationField: ${schemaName} not found in collection ${name}`));
|
if (sourceKeyValue === undefined) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
variables
|
variables
|
||||||
.parseVariable(variableString, formVariable)
|
.parseVariable(variableString, formVariable)
|
||||||
.then((value) => {
|
.then((value) => {
|
||||||
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
|
nextTick(() => {
|
||||||
|
field.value = transformVariableValue(value, { targetCollectionField: collectionFieldRef.current });
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
}, [schemaName.includes('.') ? formValue[schemaName.split('.')[0]] : null]);
|
}, [sourceKeyValue]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useLazyLoadDisplayAssociationFieldsOfForm;
|
export default useLazyLoadDisplayAssociationFieldsOfForm;
|
||||||
|
@ -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('.');
|
||||||
|
};
|
@ -277,13 +277,6 @@ VariablesProvider.displayName = 'VariablesProvider';
|
|||||||
|
|
||||||
export default VariablesProvider;
|
export default VariablesProvider;
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否应该请求关系字段的数据。如果是 null 则可以确定后端的数据为空,此时不需要请求;如果是 undefined 则需要请求。
|
|
||||||
*
|
|
||||||
* 注意:如果后端接口的这一 “规则” 发生了变更,那么可能会出现问题。
|
|
||||||
* @param value
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function shouldToRequest(value) {
|
function shouldToRequest(value) {
|
||||||
// fix https://nocobase.height.app/T-2502
|
// fix https://nocobase.height.app/T-2502
|
||||||
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
||||||
@ -291,5 +284,5 @@ function shouldToRequest(value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value === undefined;
|
return _.isEmpty(value);
|
||||||
}
|
}
|
||||||
|
@ -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`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,6 +14,10 @@ interface Deps {
|
|||||||
export const transformVariableValue = (value: any, deps: Deps) => {
|
export const transformVariableValue = (value: any, deps: Deps) => {
|
||||||
const { targetCollectionField } = deps;
|
const { targetCollectionField } = deps;
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!targetCollectionField) {
|
if (!targetCollectionField) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -41,3 +41,7 @@ export const hasEmptyValue = (objOrArr: object | any[]) => {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const nextTick = (fn: () => void) => {
|
||||||
|
setTimeout(fn);
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user