Skip to content

Instantly share code, notes, and snippets.

@pvaladez
Created June 29, 2024 06:26
Show Gist options
  • Select an option

  • Save pvaladez/4015919fd6d19bbf02427a396bb0b214 to your computer and use it in GitHub Desktop.

Select an option

Save pvaladez/4015919fd6d19bbf02427a396bb0b214 to your computer and use it in GitHub Desktop.
Payload CMS Custom Group Field with Ability to Hide Label
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ErrorPill } from 'payload/components';
import type { Props } from 'payload/components/fields/Group';
import {
createNestedFieldPath,
FieldDescription,
RenderFields,
useFormSubmitted,
} from 'payload/components/forms';
import { useCollapsible } from 'payload/dist/admin/components/elements/Collapsible/provider';
import {
GroupProvider,
useGroup,
} from 'payload/dist/admin/components/forms/field-types/Group/provider';
import { useRow } from 'payload/dist/admin/components/forms/field-types/Row/provider';
import { fieldBaseClass } from 'payload/dist/admin/components/forms/field-types/shared';
import { useTabs } from 'payload/dist/admin/components/forms/field-types/Tabs/provider';
import { WatchChildErrors } from 'payload/dist/admin/components/forms/WatchChildErrors';
import withCondition from 'payload/dist/admin/components/forms/withCondition';
import { getTranslation } from 'payload/utilities';
// import './index.scss';
const baseClass = 'group-field';
const Group: React.FC<Props> = props => {
const {
name,
admin: { className, description, hideGutter = false, readOnly, style, width },
fieldTypes,
fields,
custom,
forceRender = false,
indexPath,
label,
path: pathFromProps,
permissions,
} = props;
const withinCollapsible = useCollapsible();
const isWithinGroup = useGroup();
const isWithinRow = useRow();
const isWithinTab = useTabs();
const { i18n } = useTranslation();
const submitted = useFormSubmitted();
const [errorCount, setErrorCount] = React.useState(undefined);
const groupHasErrors = submitted && errorCount > 0;
const path = pathFromProps || name;
const isTopLevel = !(isWithinGroup || isWithinRow);
return (
<div
className={[
fieldBaseClass,
baseClass,
isTopLevel && `${baseClass}--top-level`,
withinCollapsible && `${baseClass}--within-collapsible`,
isWithinGroup && `${baseClass}--within-group`,
isWithinRow && `${baseClass}--within-row`,
isWithinTab && `${baseClass}--within-tab`,
!hideGutter && isWithinGroup && `${baseClass}--gutter`,
groupHasErrors && `${baseClass}--has-error`,
className,
]
.filter(Boolean)
.join(' ')}
id={`field-${path.replace(/\./g, '__')}`}
style={{
...style,
width,
}}
>
<WatchChildErrors fieldSchema={fields} path={path} setErrorCount={setErrorCount} />
<GroupProvider>
<div className={`${baseClass}__wrap`}>
<div className={`${baseClass}__header`}>
{(label || description) && (
<header>
{!custom?.hideLabel && label && (
<h3 className={`${baseClass}__title`}>
{getTranslation(label, i18n)}
</h3>
)}
<FieldDescription
className={`field-description-${path.replace(/\./g, '__')}`}
description={description}
path={path}
value={null}
/>
</header>
)}
{groupHasErrors && <ErrorPill count={errorCount} withMessage />}
</div>
<RenderFields
fieldSchema={fields.map(subField => ({
...subField,
path: createNestedFieldPath(path, subField),
}))}
fieldTypes={fieldTypes}
forceRender={forceRender}
indexPath={indexPath}
margins="small"
permissions={permissions?.fields}
readOnly={readOnly}
/>
</div>
</GroupProvider>
</div>
);
};
export default withCondition(Group);
import type { Field, GroupField } from 'payload/types';
import CustomGroupFieldComponent from 'CustomGroupFieldComponent';
import deepMerge from '../utilities/deepMerge';
interface GroupProps {
label?: string;
name: string;
hideLabel?: boolean;
fields: Field[];
admin?: GroupField['admin'];
overrides?: Partial<Field>;
}
type Group = ({ label, name, hideLabel, fields, admin, overrides }: GroupProps) => Field;
export const group: Group = ({
label = undefined,
name,
hideLabel = false,
fields = [],
admin = {},
overrides = {},
}) => {
return deepMerge<Field, Partial<Field>>(
{
label,
name,
type: 'group',
admin: {
components: {
Field: CustomGroupFieldComponent,
},
...admin,
},
fields,
custom: {
hideLabel,
},
},
overrides,
);
};
import type { CollectionConfig } from 'payload/types';
import { group } from 'groupField';
export const Pages: CollectionConfig = {
slug: 'pages',
fields: [
{
type: 'collapsible',
label: 'Button in Collapsible',
fields: [
group({
name: 'buttonWithGroupedFields',
hideLabel: true,
admin: {
hideGutter: true,
},
fields: [
{
label: 'Show Button',
type: 'checkbox',
name: 'showButton',
},
],
}),
],
},
],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment