fix(ui): field.admin.condition data attribute missing document ID when document is being edited (#13676)

Fixes https://github.com/payloadcms/payload/issues/10379

During form state requests, the passed `data` did not have access to the
document ID. This was because the data we use came from the client,
passed as an argument. The client did not pass data that included the
document ID.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1211203844178567
This commit is contained in:
Alessio Gravili
2025-09-02 18:14:07 -07:00
committed by GitHub
parent 9b109339ee
commit a11586811e
4 changed files with 176 additions and 113 deletions

View File

@@ -15,6 +15,7 @@ import {
// throttleTest,
} from '../../../helpers.js'
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
import { assertNetworkRequests } from '../../../helpers/e2e/assertNetworkRequests.js'
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
import { reInitializeDB } from '../../../helpers/reInitializeDB.js'
import { RESTClient } from '../../../helpers/rest.js'
@@ -99,6 +100,53 @@ describe('Conditional Logic', () => {
expect(true).toBe(true)
})
test('ensure conditions receive document ID during form state request', async () => {
await page.goto(url.create)
const fieldOnlyVisibleIfNoID = page.locator('#field-fieldWithDocIDCondition')
await expect(fieldOnlyVisibleIfNoID).toBeVisible()
const textField = page.locator('#field-text')
await assertNetworkRequests(
page,
'/admin/collections/conditional-logic',
async () => {
await textField.fill('some text')
},
{
minimumNumberOfRequests: 1,
},
)
await assertNetworkRequests(
page,
'/api/conditional-logic',
async () => {
await saveDocAndAssert(page)
},
{
minimumNumberOfRequests: 1,
},
)
await expect(fieldOnlyVisibleIfNoID).toBeHidden()
// Fill text and wait for form state request to come back
await assertNetworkRequests(
page,
'/admin/collections/conditional-logic',
async () => {
await textField.fill('updated text')
},
{
minimumNumberOfRequests: 1,
},
)
await expect(fieldOnlyVisibleIfNoID).toBeHidden()
})
test('should conditionally render custom field that renders a Payload field', async () => {
await page.goto(url.create)

View File

@@ -17,6 +17,13 @@ const ConditionalLogic: CollectionConfig = {
name: 'toggleField',
type: 'checkbox',
},
{
name: 'fieldWithDocIDCondition',
type: 'text',
admin: {
condition: ({ id }) => !id,
},
},
{
name: 'fieldWithCondition',
type: 'text',

View File

@@ -149,7 +149,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: string;
defaultIDType: number;
};
globals: {};
globalsSelect: {};
@@ -215,7 +215,7 @@ export interface LocalizedTextReference2 {
* via the `definition` "users".
*/
export interface User {
id: string;
id: number;
canViewConditionalField?: boolean | null;
updatedAt: string;
createdAt: string;
@@ -240,7 +240,7 @@ export interface User {
* via the `definition` "select-versions-fields".
*/
export interface SelectVersionsField {
id: string;
id: number;
hasMany?: ('a' | 'b' | 'c' | 'd')[] | null;
array?:
| {
@@ -265,7 +265,7 @@ export interface SelectVersionsField {
* via the `definition` "array-fields".
*/
export interface ArrayField {
id: string;
id: number;
title?: string | null;
items: {
text: string;
@@ -369,7 +369,7 @@ export interface ArrayField {
* via the `definition` "block-fields".
*/
export interface BlockField {
id: string;
id: number;
blocks: (ContentBlock | NoBlockname | NumberBlock | SubBlocksBlock | TabsBlock)[];
duplicate: (ContentBlock | NoBlockname | NumberBlock | SubBlocksBlock | TabsBlock)[];
collapsedByDefaultBlocks: (
@@ -500,7 +500,7 @@ export interface BlockField {
| null;
relationshipBlocks?:
| {
relationship?: (string | null) | TextField;
relationship?: (number | null) | TextField;
id?: string | null;
blockName?: string | null;
blockType: 'relationships';
@@ -697,7 +697,7 @@ export interface LocalizedTabsBlock {
* via the `definition` "text-fields".
*/
export interface TextField {
id: string;
id: number;
text: string;
hiddenTextField?: string | null;
/**
@@ -749,7 +749,7 @@ export interface TextField {
* via the `definition` "checkbox-fields".
*/
export interface CheckboxField {
id: string;
id: number;
checkbox: boolean;
checkboxNotRequired?: boolean | null;
updatedAt: string;
@@ -760,7 +760,7 @@ export interface CheckboxField {
* via the `definition` "code-fields".
*/
export interface CodeField {
id: string;
id: number;
javascript?: string | null;
typescript?: string | null;
json?: string | null;
@@ -775,7 +775,7 @@ export interface CodeField {
* via the `definition` "collapsible-fields".
*/
export interface CollapsibleField {
id: string;
id: number;
text: string;
group: {
textWithinGroup?: string | null;
@@ -808,9 +808,10 @@ export interface CollapsibleField {
* via the `definition` "conditional-logic".
*/
export interface ConditionalLogic {
id: string;
id: number;
text: string;
toggleField?: boolean | null;
fieldWithDocIDCondition?: string | null;
fieldWithCondition?: string | null;
fieldWithOperationCondition?: string | null;
customFieldWithField?: string | null;
@@ -921,7 +922,7 @@ export interface CustomRowId {
* via the `definition` "date-fields".
*/
export interface DateField {
id: string;
id: number;
default: string;
timeOnly?: string | null;
timeOnlyWithMiliseconds?: string | null;
@@ -966,7 +967,7 @@ export interface DateField {
* via the `definition` "email-fields".
*/
export interface EmailField {
id: string;
id: number;
email: string;
localizedEmail?: string | null;
emailWithAutocomplete?: string | null;
@@ -991,7 +992,7 @@ export interface EmailField {
* via the `definition` "radio-fields".
*/
export interface RadioField {
id: string;
id: number;
radio?: ('one' | 'two' | 'three') | null;
radioWithJsxLabelOption?: ('one' | 'two' | 'three') | null;
updatedAt: string;
@@ -1002,7 +1003,7 @@ export interface RadioField {
* via the `definition` "group-fields".
*/
export interface GroupField {
id: string;
id: number;
/**
* This is a group.
*/
@@ -1084,22 +1085,22 @@ export interface GroupField {
select?: ('one' | 'two')[] | null;
};
localizedGroupRel?: {
email?: (string | null) | EmailField;
email?: (number | null) | EmailField;
};
localizedGroupManyRel?: {
email?: (string | EmailField)[] | null;
email?: (number | EmailField)[] | null;
};
localizedGroupPolyRel?: {
email?: {
relationTo: 'email-fields';
value: string | EmailField;
value: number | EmailField;
} | null;
};
localizedGroupPolyHasManyRel?: {
email?:
| {
relationTo: 'email-fields';
value: string | EmailField;
value: number | EmailField;
}[]
| null;
};
@@ -1153,30 +1154,30 @@ export interface RowField {
* via the `definition` "indexed-fields".
*/
export interface IndexedField {
id: string;
id: number;
text: string;
uniqueText?: string | null;
uniqueRelationship?: (string | null) | TextField;
uniqueHasManyRelationship?: (string | TextField)[] | null;
uniqueHasManyRelationship_2?: (string | TextField)[] | null;
uniqueRelationship?: (number | null) | TextField;
uniqueHasManyRelationship?: (number | TextField)[] | null;
uniqueHasManyRelationship_2?: (number | TextField)[] | null;
uniquePolymorphicRelationship?: {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
} | null;
uniquePolymorphicRelationship_2?: {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
} | null;
uniqueHasManyPolymorphicRelationship?:
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}[]
| null;
uniqueHasManyPolymorphicRelationship_2?:
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}[]
| null;
uniqueRequiredText: string;
@@ -1212,7 +1213,7 @@ export interface IndexedField {
* via the `definition` "json-fields".
*/
export interface JsonField {
id: string;
id: number;
json?: {
array?: {
object?: {
@@ -1253,7 +1254,7 @@ export interface JsonField {
* via the `definition` "number-fields".
*/
export interface NumberField {
id: string;
id: number;
number?: number | null;
min?: number | null;
max?: number | null;
@@ -1288,7 +1289,7 @@ export interface NumberField {
* via the `definition` "point-fields".
*/
export interface PointField {
id: string;
id: number;
/**
* @minItems 2
* @maxItems 2
@@ -1319,83 +1320,83 @@ export interface PointField {
* via the `definition` "relationship-fields".
*/
export interface RelationshipField {
id: string;
id: number;
text?: string | null;
relationship:
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}
| {
relationTo: 'array-fields';
value: string | ArrayField;
value: number | ArrayField;
};
relationHasManyPolymorphic?:
| (
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}
| {
relationTo: 'array-fields';
value: string | ArrayField;
value: number | ArrayField;
}
)[]
| null;
relationToSelf?: (string | null) | RelationshipField;
relationToSelfSelectOnly?: (string | null) | RelationshipField;
relationWithAllowCreateToFalse?: (string | null) | User;
relationWithAllowEditToFalse?: (string | null) | User;
relationWithDynamicDefault?: (string | null) | User;
relationToSelf?: (number | null) | RelationshipField;
relationToSelfSelectOnly?: (number | null) | RelationshipField;
relationWithAllowCreateToFalse?: (number | null) | User;
relationWithAllowEditToFalse?: (number | null) | User;
relationWithDynamicDefault?: (number | null) | User;
relationHasManyWithDynamicDefault?: {
relationTo: 'users';
value: string | User;
value: number | User;
} | null;
relationshipWithMin?: (string | TextField)[] | null;
relationshipWithMax?: (string | TextField)[] | null;
relationshipHasMany?: (string | TextField)[] | null;
relationshipWithMin?: (number | TextField)[] | null;
relationshipWithMax?: (number | TextField)[] | null;
relationshipHasMany?: (number | TextField)[] | null;
array?:
| {
relationship?: (string | null) | TextField;
relationship?: (number | null) | TextField;
id?: string | null;
}[]
| null;
relationshipWithMinRows?:
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}[]
| null;
relationToRow?: (string | null) | RowField;
relationToRowMany?: (string | RowField)[] | null;
relationshipDrawer?: (string | null) | TextField;
relationshipDrawerReadOnly?: (string | null) | TextField;
relationshipDrawer?: (number | null) | TextField;
relationshipDrawerReadOnly?: (number | null) | TextField;
polymorphicRelationshipDrawer?:
| ({
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
} | null)
| ({
relationTo: 'array-fields';
value: string | ArrayField;
value: number | ArrayField;
} | null);
relationshipDrawerHasMany?: (string | TextField)[] | null;
relationshipDrawerHasMany?: (number | TextField)[] | null;
relationshipDrawerHasManyPolymorphic?:
| (
| {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
}
| {
relationTo: 'array-fields';
value: string | ArrayField;
value: number | ArrayField;
}
)[]
| null;
relationshipDrawerWithAllowCreateFalse?: (string | null) | TextField;
relationshipDrawerWithAllowCreateFalse?: (number | null) | TextField;
relationshipDrawerWithFilterOptions?: {
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
} | null;
updatedAt: string;
createdAt: string;
@@ -1405,7 +1406,7 @@ export interface RelationshipField {
* via the `definition` "select-fields".
*/
export interface SelectField {
id: string;
id: number;
select?: ('one' | 'two' | 'three') | null;
selectReadOnly?: ('one' | 'two' | 'three') | null;
selectHasMany?: ('one' | 'two' | 'three' | 'four' | 'five' | 'six')[] | null;
@@ -1435,7 +1436,7 @@ export interface SelectField {
* via the `definition` "tabs-fields-2".
*/
export interface TabsFields2 {
id: string;
id: number;
tabsInArray?:
| {
text?: string | null;
@@ -1453,7 +1454,7 @@ export interface TabsFields2 {
* via the `definition` "tabs-fields".
*/
export interface TabsField {
id: string;
id: number;
/**
* This should not collapse despite there being many tabs pushing the main fields open.
*/
@@ -1555,9 +1556,9 @@ export interface TabWithName {
* via the `definition` "uploads".
*/
export interface Upload {
id: string;
id: number;
text?: string | null;
media?: (string | null) | Upload;
media?: (number | null) | Upload;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -1575,9 +1576,9 @@ export interface Upload {
* via the `definition` "uploads2".
*/
export interface Uploads2 {
id: string;
id: number;
text?: string | null;
media?: (string | null) | Uploads2;
media?: (number | null) | Uploads2;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -1595,8 +1596,8 @@ export interface Uploads2 {
* via the `definition` "uploads3".
*/
export interface Uploads3 {
id: string;
media?: (string | null) | Uploads3;
id: number;
media?: (number | null) | Uploads3;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -1614,9 +1615,9 @@ export interface Uploads3 {
* via the `definition` "uploads-multi".
*/
export interface UploadsMulti {
id: string;
id: number;
text?: string | null;
media?: (string | Upload)[] | null;
media?: (number | Upload)[] | null;
updatedAt: string;
createdAt: string;
}
@@ -1625,16 +1626,16 @@ export interface UploadsMulti {
* via the `definition` "uploads-poly".
*/
export interface UploadsPoly {
id: string;
id: number;
text?: string | null;
media?:
| ({
relationTo: 'uploads';
value: string | Upload;
value: number | Upload;
} | null)
| ({
relationTo: 'uploads2';
value: string | Uploads2;
value: number | Uploads2;
} | null);
updatedAt: string;
createdAt: string;
@@ -1644,17 +1645,17 @@ export interface UploadsPoly {
* via the `definition` "uploads-multi-poly".
*/
export interface UploadsMultiPoly {
id: string;
id: number;
text?: string | null;
media?:
| (
| {
relationTo: 'uploads';
value: string | Upload;
value: number | Upload;
}
| {
relationTo: 'uploads2';
value: string | Uploads2;
value: number | Uploads2;
}
)[]
| null;
@@ -1666,11 +1667,11 @@ export interface UploadsMultiPoly {
* via the `definition` "uploads-restricted".
*/
export interface UploadsRestricted {
id: string;
id: number;
text?: string | null;
uploadWithoutRestriction?: (string | null) | Upload;
uploadWithAllowCreateFalse?: (string | null) | Upload;
uploadMultipleWithAllowCreateFalse?: (string | Upload)[] | null;
uploadWithoutRestriction?: (number | null) | Upload;
uploadWithAllowCreateFalse?: (number | null) | Upload;
uploadMultipleWithAllowCreateFalse?: (number | Upload)[] | null;
updatedAt: string;
createdAt: string;
}
@@ -1679,7 +1680,7 @@ export interface UploadsRestricted {
* via the `definition` "ui-fields".
*/
export interface UiField {
id: string;
id: number;
text: string;
updatedAt: string;
createdAt: string;
@@ -1689,39 +1690,39 @@ export interface UiField {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: string;
id: number;
document?:
| ({
relationTo: 'users';
value: string | User;
value: number | User;
} | null)
| ({
relationTo: 'select-versions-fields';
value: string | SelectVersionsField;
value: number | SelectVersionsField;
} | null)
| ({
relationTo: 'array-fields';
value: string | ArrayField;
value: number | ArrayField;
} | null)
| ({
relationTo: 'block-fields';
value: string | BlockField;
value: number | BlockField;
} | null)
| ({
relationTo: 'checkbox-fields';
value: string | CheckboxField;
value: number | CheckboxField;
} | null)
| ({
relationTo: 'code-fields';
value: string | CodeField;
value: number | CodeField;
} | null)
| ({
relationTo: 'collapsible-fields';
value: string | CollapsibleField;
value: number | CollapsibleField;
} | null)
| ({
relationTo: 'conditional-logic';
value: string | ConditionalLogic;
value: number | ConditionalLogic;
} | null)
| ({
relationTo: 'custom-id';
@@ -1729,27 +1730,27 @@ export interface PayloadLockedDocument {
} | null)
| ({
relationTo: 'custom-tab-id';
value: string | CustomTabId;
value: number | CustomTabId;
} | null)
| ({
relationTo: 'custom-row-id';
value: string | CustomRowId;
value: number | CustomRowId;
} | null)
| ({
relationTo: 'date-fields';
value: string | DateField;
value: number | DateField;
} | null)
| ({
relationTo: 'email-fields';
value: string | EmailField;
value: number | EmailField;
} | null)
| ({
relationTo: 'radio-fields';
value: string | RadioField;
value: number | RadioField;
} | null)
| ({
relationTo: 'group-fields';
value: string | GroupField;
value: number | GroupField;
} | null)
| ({
relationTo: 'row-fields';
@@ -1757,76 +1758,76 @@ export interface PayloadLockedDocument {
} | null)
| ({
relationTo: 'indexed-fields';
value: string | IndexedField;
value: number | IndexedField;
} | null)
| ({
relationTo: 'json-fields';
value: string | JsonField;
value: number | JsonField;
} | null)
| ({
relationTo: 'number-fields';
value: string | NumberField;
value: number | NumberField;
} | null)
| ({
relationTo: 'point-fields';
value: string | PointField;
value: number | PointField;
} | null)
| ({
relationTo: 'relationship-fields';
value: string | RelationshipField;
value: number | RelationshipField;
} | null)
| ({
relationTo: 'select-fields';
value: string | SelectField;
value: number | SelectField;
} | null)
| ({
relationTo: 'tabs-fields-2';
value: string | TabsFields2;
value: number | TabsFields2;
} | null)
| ({
relationTo: 'tabs-fields';
value: string | TabsField;
value: number | TabsField;
} | null)
| ({
relationTo: 'text-fields';
value: string | TextField;
value: number | TextField;
} | null)
| ({
relationTo: 'uploads';
value: string | Upload;
value: number | Upload;
} | null)
| ({
relationTo: 'uploads2';
value: string | Uploads2;
value: number | Uploads2;
} | null)
| ({
relationTo: 'uploads3';
value: string | Uploads3;
value: number | Uploads3;
} | null)
| ({
relationTo: 'uploads-multi';
value: string | UploadsMulti;
value: number | UploadsMulti;
} | null)
| ({
relationTo: 'uploads-poly';
value: string | UploadsPoly;
value: number | UploadsPoly;
} | null)
| ({
relationTo: 'uploads-multi-poly';
value: string | UploadsMultiPoly;
value: number | UploadsMultiPoly;
} | null)
| ({
relationTo: 'uploads-restricted';
value: string | UploadsRestricted;
value: number | UploadsRestricted;
} | null)
| ({
relationTo: 'ui-fields';
value: string | UiField;
value: number | UiField;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
updatedAt: string;
createdAt: string;
@@ -1836,10 +1837,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string;
id: number;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
key?: string | null;
value?:
@@ -1859,7 +1860,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string;
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -2452,6 +2453,7 @@ export interface CollapsibleFieldsSelect<T extends boolean = true> {
export interface ConditionalLogicSelect<T extends boolean = true> {
text?: T;
toggleField?: T;
fieldWithDocIDCondition?: T;
fieldWithCondition?: T;
fieldWithOperationCondition?: T;
customFieldWithField?: T;