diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/lazyLoadAssociationFields1.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/lazyLoadAssociationFields1.test.ts index 5a10626d68..4fd8515646 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/lazyLoadAssociationFields1.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/lazyLoadAssociationFields1.test.ts @@ -13,7 +13,7 @@ import { oneSubformWithMultiLevelAssociationFields, test, } from '@nocobase/test/e2e'; -import { T2614, T2615, T2845, T2993 } from './templatesOfBug'; +import { T2614, T2615, T2845, T2993, T4596 } from './templatesOfBug'; test.describe('display association fields', () => { test('form: should display correctly', async ({ page, mockPage, mockRecord }) => { @@ -188,4 +188,22 @@ test.describe('display association fields', () => { new RegExp(record.m2o.m2oOfTarget1.m2oOfTarget2.nickname), ); }); + + // https://nocobase.height.app/T-4596 + test('Non-ID source key', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(T4596).waitForInit(); + const record = await mockRecord('collectionA', 2); + await nocoPage.goto(); + + await page + .getByLabel('block-item-CollectionField-collectionA-form-collectionA.collectionAM2OField-') + .getByTestId('select-object-single') + .click(); + await page.getByRole('option', { name: record.collectionAM2OField.id, exact: true }).click(); + await expect( + page + .getByLabel('block-item-CollectionField-collectionA-form-collectionA.collectionAM2OField.') + .getByText(record.collectionAM2OField.collectionBM2OField.singleLineText), + ).toBeVisible(); + }); }); diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts index 2346e90090..b70df90e48 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts @@ -9908,3 +9908,245 @@ export const expressionTemplateInLinkageRules = { 'x-index': 1, }, }; +export const T4596 = { + collections: [ + { + name: 'collectionC', + fields: [ + { + interface: 'input', + name: 'singleLineText', + }, + ], + }, + { + name: 'collectionB', + fields: [ + { + name: 'collectionBM2OField', + interface: 'm2o', + target: 'collectionC', + sourceKey: 'sourceKey', + }, + { + name: 'sourceKey', + interface: 'number', + }, + ], + }, + { + name: 'collectionA', + fields: [ + { + name: 'collectionAM2OField', + interface: 'm2o', + target: 'collectionB', + }, + ], + }, + ], + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + 'x-index': 1, + properties: { + '8fabihs13u3': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + 'x-index': 1, + properties: { + '3nbfdp98hnv': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + e0hd016jask: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + '1pmxkzimdau': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-acl-action': 'collectionA:create', + 'x-decorator': 'FormBlockProvider', + 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps', + 'x-decorator-props': { + dataSource: 'main', + collection: 'collectionA', + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:createForm', + 'x-component': 'CardItem', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + '3nbd62urdzh': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'FormV2', + 'x-use-component-props': 'useCreateFormBlockProps', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'form:configureFields', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + '2ljkh36y6n7': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + seg282crfdx: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + collectionAM2OField: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'collectionA.collectionAM2OField', + 'x-component-props': { + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + 'x-uid': 'do4yzr3scts', + 'x-async': false, + }, + }, + 'x-uid': 'f5omerdi0kn', + 'x-async': false, + }, + }, + 'x-uid': '1vxr8iqbc1m', + 'x-async': false, + }, + '8ez1aq0wv99': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.2.4-alpha', + 'x-index': 2, + properties: { + qxh5iov1310: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + properties: { + 'collectionAM2OField.collectionBM2OField': { + 'x-uid': 'xm0dkxh1m8o', + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-read-pretty': true, + 'x-component-props': { + 'pattern-disable': true, + fieldNames: { + label: 'singleLineText', + value: 'id', + }, + }, + 'x-decorator': 'FormItem', + 'x-collection-field': 'collectionA.collectionAM2OField.collectionBM2OField', + 'x-app-version': '1.2.4-alpha', + 'x-index': 1, + 'x-async': false, + }, + }, + 'x-uid': '34edcrftixd', + 'x-async': false, + }, + }, + 'x-uid': 'ewykrxx0ln4', + 'x-async': false, + }, + }, + 'x-uid': 'wnea81u7ir5', + 'x-async': false, + }, + '2kbvvxyxgzj': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'createForm:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + layout: 'one-column', + style: { + marginTop: 'var(--nb-spacing)', + }, + }, + 'x-app-version': '1.2.4-alpha', + 'x-index': 2, + 'x-uid': '0hstjjkvw9x', + 'x-async': false, + }, + }, + 'x-uid': 'qsxevezydxa', + 'x-async': false, + }, + }, + 'x-uid': 'zh9641pt4ws', + 'x-async': false, + }, + }, + 'x-uid': 'ps0spq4ya0k', + 'x-async': false, + }, + }, + 'x-uid': 'uy0bksjg6qk', + 'x-async': false, + }, + }, + 'x-uid': 'l5nc16o4pi5', + 'x-async': false, + }, + }, + 'x-uid': 'oqkl5enxwq1', + 'x-async': true, + }, +}; diff --git a/packages/core/client/src/variables/VariablesProvider.tsx b/packages/core/client/src/variables/VariablesProvider.tsx index 547305b2f2..bc765a42eb 100644 --- a/packages/core/client/src/variables/VariablesProvider.tsx +++ b/packages/core/client/src/variables/VariablesProvider.tsx @@ -52,7 +52,7 @@ const getFieldPath = (variablePath: string, variablesStore: Record { const ctxRef = useRef>({}); const api = useAPIClient(); - const { getCollectionJoinField } = useCollectionManager_deprecated(); + const { getCollectionJoinField, getCollection } = useCollectionManager_deprecated(); const compile = useCompile(); const { builtinVariables } = useBuiltInVariables(); @@ -97,11 +97,14 @@ const VariablesProvider = ({ children }) => { const key = list[index]; const { fieldPath } = getFieldPath(list.slice(0, index + 1).join('.'), _variableToCollectionName); const associationField: CollectionFieldOptions_deprecated = getCollectionJoinField(fieldPath, dataSource); + const collectionPrimaryKey = getCollection(collectionName)?.getPrimaryKey(); if (Array.isArray(current)) { const result = current.map((item) => { - if (shouldToRequest(item?.[key]) && item?.id != null) { + if (shouldToRequest(item?.[key]) && item?.[collectionPrimaryKey] != null) { if (associationField?.target) { - const url = `/${collectionName}/${item.id}/${key}:${getAction(associationField.type)}`; + const url = `/${collectionName}/${ + item[associationField.sourceKey || collectionPrimaryKey] + }/${key}:${getAction(associationField.type)}`; if (hasRequested(url)) { return getRequested(url); } @@ -125,8 +128,10 @@ const VariablesProvider = ({ children }) => { return item?.[key]; }); current = removeThroughCollectionFields(_.flatten(await Promise.all(result)), associationField); - } else if (shouldToRequest(current[key]) && current.id != null && associationField?.target) { - const url = `/${collectionName}/${current.id}/${key}:${getAction(associationField.type)}`; + } else if (shouldToRequest(current[key]) && current[collectionPrimaryKey] != null && associationField?.target) { + const url = `/${collectionName}/${ + current[associationField.sourceKey || collectionPrimaryKey] + }/${key}:${getAction(associationField.type)}`; let data = null; if (hasRequested(url)) { data = await getRequested(url); diff --git a/packages/core/client/src/variables/__tests__/useVariables.test.tsx b/packages/core/client/src/variables/__tests__/useVariables.test.tsx index 83cd499f61..cb47b02997 100644 --- a/packages/core/client/src/variables/__tests__/useVariables.test.tsx +++ b/packages/core/client/src/variables/__tests__/useVariables.test.tsx @@ -66,6 +66,11 @@ vi.mock('../../collection-manager', async () => { }; } }, + getCollection: () => { + return { + getPrimaryKey: () => 'id', + }; + }, }; }, CollectionManagerPane: null,