Files
payloadcms/test/fields/collections/ConditionalLogic/index.ts
Jacob Fletcher 1502e09581 fix(ui): automatically subscribes custom fields to conditional logic (#9928)
Currently, custom components do not respect `admin.condition` unless
manually wrapped with the `withCondition` HOC, like all default fields
currently do. This should not be a requirement of component authors.
Instead, we can automatically detect custom client and server fields and
wrap them with the underlying `WatchCondition` component which will
subscribe to the `passesCondition` property within client-side form
state.

For my future self: there are potentially multiple instances where
fields subscribe to conditions duplicately, such as when rendering a
default Payload field within a custom field component. This was always a
problem and it is non-breaking, but needs to be reevaluated and removed
in the future for performance. Only the default fields that Payload
renders client-side need to subscribe to field conditions in this way.
When importing a Payload field into your custom field component, for
example, it should not include the HOC, because custom components now
watch conditions themselves.
2024-12-13 14:12:37 -05:00

189 lines
4.2 KiB
TypeScript

import type { CollectionConfig } from 'payload'
import { conditionalLogicSlug } from '../../slugs.js'
const ConditionalLogic: CollectionConfig = {
slug: conditionalLogicSlug,
admin: {
useAsTitle: 'text',
},
fields: [
{
name: 'text',
type: 'text',
required: true,
},
{
name: 'toggleField',
type: 'checkbox',
},
{
name: 'fieldWithCondition',
type: 'text',
admin: {
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'customFieldWithField',
type: 'text',
admin: {
components: {
Field: '/collections/ConditionalLogic/CustomFieldWithField',
},
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'customFieldWithHOC',
label: 'Custom Field With HOC (legacy)',
type: 'text',
admin: {
components: {
Field: '/collections/ConditionalLogic/CustomFieldWithHOC',
},
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'customClientFieldWithCondition',
type: 'text',
admin: {
components: {
Field: '/collections/ConditionalLogic/CustomClientField',
},
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'customServerFieldWithCondition',
type: 'text',
admin: {
components: {
Field: '/collections/ConditionalLogic/CustomServerField',
},
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'conditionalRichText',
type: 'richText',
admin: {
condition: ({ toggleField }) => Boolean(toggleField),
},
},
{
name: 'userConditional',
type: 'text',
admin: {
condition: (_data, _siblingData, { user }) => {
return Boolean(user?.canViewConditionalField)
},
},
},
{
name: 'parentGroup',
type: 'group',
fields: [
{
name: 'enableParentGroupFields',
type: 'checkbox',
defaultValue: false,
},
{
name: 'siblingField',
type: 'text',
admin: {
description: 'Ensures we can rely on nested fields within `data`.',
condition: ({ parentGroup }) => Boolean(parentGroup?.enableParentGroupFields),
},
},
],
},
{
name: 'reliesOnParentGroup',
type: 'text',
admin: {
description: 'Ensures we can rely on nested fields within `siblingsData`.',
condition: (_, { parentGroup }) => Boolean(parentGroup?.enableParentGroupFields),
},
},
{
name: 'groupSelection',
type: 'select',
options: ['group1', 'group2'],
},
{
name: 'group1',
type: 'group',
fields: [
{
name: 'group1Field',
type: 'text',
},
],
admin: {
condition: ({ groupSelection }) => groupSelection === 'group1',
},
},
{
name: 'group2',
type: 'group',
fields: [
{
name: 'group2Field',
type: 'text',
},
],
admin: {
condition: ({ groupSelection }) => groupSelection === 'group2',
},
},
{
name: 'enableConditionalFields',
type: 'checkbox',
},
{
name: 'arrayWithConditionalField',
type: 'array',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'textWithCondition',
type: 'text',
admin: {
condition: (data) => data.enableConditionalFields,
},
},
],
},
{
name: 'blocksWithConditionalField',
type: 'blocks',
blocks: [
{
slug: 'blockWithConditionalField',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'textWithCondition',
type: 'text',
admin: {
condition: (data) => data.enableConditionalFields,
},
},
],
},
],
},
],
}
export default ConditionalLogic