diff --git a/src/admin/components/forms/Form/createNestedFieldPath.ts b/src/admin/components/forms/Form/createNestedFieldPath.ts new file mode 100644 index 0000000000..9f407ef496 --- /dev/null +++ b/src/admin/components/forms/Form/createNestedFieldPath.ts @@ -0,0 +1,17 @@ +import { Field, fieldAffectsData } from '../../../../fields/config/types'; + +export const createNestedFieldPath = (parentPath: string, field: Field): string => { + if (parentPath) { + if (fieldAffectsData(field)) { + return `${parentPath}.${field.name}`; + } + + return parentPath; + } + + if (fieldAffectsData(field)) { + return field.name; + } + + return ''; +}; diff --git a/src/admin/components/forms/Form/getSiblingData.ts b/src/admin/components/forms/Form/getSiblingData.ts index 849b2a5724..0ee25d8e05 100644 --- a/src/admin/components/forms/Form/getSiblingData.ts +++ b/src/admin/components/forms/Form/getSiblingData.ts @@ -8,9 +8,25 @@ const getSiblingData = (fields: Fields, path: string): Data => { } const siblingFields = {}; - // If this field is nested - // We can provide a list of sibling fields - const parentFieldPath = path.substring(0, path.lastIndexOf('.') + 1); + // Determine if the last segment of the path is an array-based row + const pathSegments = path.split('.'); + const lastSegment = pathSegments[pathSegments.length - 1]; + const lastSegmentIsRowIndex = !Number.isNaN(Number(lastSegment)); + + let parentFieldPath: string; + + if (lastSegmentIsRowIndex) { + // If the last segment is a row index, + // the sibling data is that row's contents + // so create a parent field path that will + // retrieve all contents of that row index only + parentFieldPath = `${path}.`; + } else { + // Otherwise, the last path segment is a field name + // and it should be removed + parentFieldPath = path.substring(0, path.lastIndexOf('.') + 1); + } + Object.keys(fields).forEach((fieldKey) => { if (!fields[fieldKey].disableFormData && fieldKey.indexOf(parentFieldPath) === 0) { siblingFields[fieldKey.replace(parentFieldPath, '')] = fields[fieldKey].value; diff --git a/src/admin/components/forms/field-types/Array/index.tsx b/src/admin/components/forms/field-types/Array/index.tsx index d324bd0605..1964b08f17 100644 --- a/src/admin/components/forms/field-types/Array/index.tsx +++ b/src/admin/components/forms/field-types/Array/index.tsx @@ -17,16 +17,16 @@ import { useDocumentInfo } from '../../../utilities/DocumentInfo'; import { useOperation } from '../../../utilities/OperationProvider'; import { Collapsible } from '../../../elements/Collapsible'; import RenderFields from '../../RenderFields'; -import { fieldAffectsData } from '../../../../../fields/config/types'; import { Props } from './types'; import { usePreferences } from '../../../utilities/Preferences'; import { ArrayAction } from '../../../elements/ArrayAction'; import { scrollToID } from '../../../../utilities/scrollToID'; import HiddenInput from '../HiddenInput'; import { RowLabel } from '../../RowLabel'; +import { getTranslation } from '../../../../../utilities/getTranslation'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; -import { getTranslation } from '../../../../../utilities/getTranslation'; const baseClass = 'array-field'; @@ -312,7 +312,7 @@ const ArrayFieldType: React.FC = (props) => { indexPath={indexPath} fieldSchema={fields.map((field) => ({ ...field, - path: `${path}.${i}${fieldAffectsData(field) ? `.${field.name}` : ''}`, + path: createNestedFieldPath(`${path}.${i}`, field), }))} /> @@ -326,10 +326,7 @@ const ArrayFieldType: React.FC = (props) => { {t('validation:requiresAtLeast', { count: minRows, - label: getTranslation(minRows - ? labels.plural - : labels.singular, - i18n) || t(minRows > 1 ? 'general:row' : 'general:rows'), + label: getTranslation(minRows ? labels.plural : labels.singular, i18n) || t(minRows > 1 ? 'general:row' : 'general:rows'), })} )} diff --git a/src/admin/components/forms/field-types/Blocks/index.tsx b/src/admin/components/forms/field-types/Blocks/index.tsx index ae49843524..adc1995a3c 100644 --- a/src/admin/components/forms/field-types/Blocks/index.tsx +++ b/src/admin/components/forms/field-types/Blocks/index.tsx @@ -23,12 +23,12 @@ import { useOperation } from '../../../utilities/OperationProvider'; import { Collapsible } from '../../../elements/Collapsible'; import { ArrayAction } from '../../../elements/ArrayAction'; import RenderFields from '../../RenderFields'; -import { fieldAffectsData } from '../../../../../fields/config/types'; import SectionTitle from './SectionTitle'; import Pill from '../../../elements/Pill'; import { scrollToID } from '../../../../utilities/scrollToID'; import HiddenInput from '../HiddenInput'; import { getTranslation } from '../../../../../utilities/getTranslation'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; @@ -345,7 +345,7 @@ const BlocksField: React.FC = (props) => { permissions={permissions?.fields} fieldSchema={blockToRender.fields.map((field) => ({ ...field, - path: `${path}.${i}${fieldAffectsData(field) ? `.${field.name}` : ''}`, + path: createNestedFieldPath(`${path}.${i}`, field), }))} indexPath={indexPath} /> diff --git a/src/admin/components/forms/field-types/Collapsible/index.tsx b/src/admin/components/forms/field-types/Collapsible/index.tsx index c6993db330..761cbce2bf 100644 --- a/src/admin/components/forms/field-types/Collapsible/index.tsx +++ b/src/admin/components/forms/field-types/Collapsible/index.tsx @@ -7,8 +7,8 @@ import { usePreferences } from '../../../utilities/Preferences'; import { DocumentPreferences } from '../../../../../preferences/types'; import { useDocumentInfo } from '../../../utilities/DocumentInfo'; import FieldDescription from '../../FieldDescription'; -import { getFieldPath } from '../getFieldPath'; import { RowLabel } from '../../RowLabel'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; @@ -101,7 +101,7 @@ const CollapsibleField: React.FC = (props) => { indexPath={indexPath} fieldSchema={fields.map((field) => ({ ...field, - path: getFieldPath(path, field), + path: createNestedFieldPath(path, field), }))} /> diff --git a/src/admin/components/forms/field-types/Group/index.tsx b/src/admin/components/forms/field-types/Group/index.tsx index 49824c2157..fa601a65fc 100644 --- a/src/admin/components/forms/field-types/Group/index.tsx +++ b/src/admin/components/forms/field-types/Group/index.tsx @@ -4,11 +4,11 @@ import RenderFields from '../../RenderFields'; import withCondition from '../../withCondition'; import FieldDescription from '../../FieldDescription'; import { Props } from './types'; -import { fieldAffectsData } from '../../../../../fields/config/types'; import { useCollapsible } from '../../../elements/Collapsible/provider'; import { GroupProvider, useGroup } from './provider'; import { useTabs } from '../Tabs/provider'; import { getTranslation } from '../../../../../utilities/getTranslation'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; @@ -60,16 +60,16 @@ const Group: React.FC = (props) => {
{(label || description) && ( -
- {label && ( -

{getTranslation(label, i18n)}

- )} - -
+
+ {label && ( +

{getTranslation(label, i18n)}

+ )} + +
)} = (props) => { indexPath={indexPath} fieldSchema={fields.map((subField) => ({ ...subField, - path: `${path}${fieldAffectsData(subField) ? `.${subField.name}` : ''}`, + path: createNestedFieldPath(path, subField), }))} />
diff --git a/src/admin/components/forms/field-types/Row/index.tsx b/src/admin/components/forms/field-types/Row/index.tsx index 594b3e920d..c03e4bc953 100644 --- a/src/admin/components/forms/field-types/Row/index.tsx +++ b/src/admin/components/forms/field-types/Row/index.tsx @@ -2,7 +2,7 @@ import React from 'react'; import RenderFields from '../../RenderFields'; import withCondition from '../../withCondition'; import { Props } from './types'; -import { getFieldPath } from '../getFieldPath'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; @@ -34,7 +34,7 @@ const Row: React.FC = (props) => { indexPath={indexPath} fieldSchema={fields.map((field) => ({ ...field, - path: getFieldPath(path, field), + path: createNestedFieldPath(path, field), }))} /> ); diff --git a/src/admin/components/forms/field-types/Tabs/index.tsx b/src/admin/components/forms/field-types/Tabs/index.tsx index 6154a74063..495625be78 100644 --- a/src/admin/components/forms/field-types/Tabs/index.tsx +++ b/src/admin/components/forms/field-types/Tabs/index.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import RenderFields from '../../RenderFields'; import withCondition from '../../withCondition'; import { Props } from './types'; -import { fieldAffectsData, tabHasName } from '../../../../../fields/config/types'; +import { tabHasName } from '../../../../../fields/config/types'; import FieldDescription from '../../FieldDescription'; import toKebabCase from '../../../../../utilities/toKebabCase'; import { useCollapsible } from '../../../elements/Collapsible/provider'; @@ -12,6 +12,7 @@ import { getTranslation } from '../../../../../utilities/getTranslation'; import { usePreferences } from '../../../utilities/Preferences'; import { DocumentPreferences } from '../../../../../preferences/types'; import { useDocumentInfo } from '../../../utilities/DocumentInfo'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import './index.scss'; @@ -123,10 +124,17 @@ const TabsField: React.FC = (props) => { readOnly={readOnly} permissions={tabHasName(activeTabConfig) ? permissions[activeTabConfig.name].fields : permissions} fieldTypes={fieldTypes} - fieldSchema={activeTabConfig.fields.map((field) => ({ - ...field, - path: `${path ? `${path}.` : ''}${tabHasName(activeTabConfig) ? `${activeTabConfig.name}.` : ''}${fieldAffectsData(field) ? field.name : ''}`, - }))} + fieldSchema={activeTabConfig.fields.map((field) => { + const pathSegments = []; + + if (path) pathSegments.push(path); + if (tabHasName(activeTabConfig)) pathSegments.push(activeTabConfig.name); + + return { + ...field, + path: createNestedFieldPath(pathSegments.join('.'), field), + }; + })} indexPath={indexPath} /> diff --git a/src/admin/components/forms/field-types/getFieldPath.ts b/src/admin/components/forms/field-types/getFieldPath.ts deleted file mode 100644 index 5bebb261a9..0000000000 --- a/src/admin/components/forms/field-types/getFieldPath.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Field, fieldAffectsData } from '../../../../fields/config/types'; - -export const getFieldPath = (path: string, field: Field): string => { - // prevents duplicate . on nesting non-named fields - const dot = path && path.slice(-1) === '.' ? '' : '.'; - return `${path ? `${path}${dot}` : ''}${fieldAffectsData(field) ? field.name : ''}`; -};