Skip to content

Commit

Permalink
feat(ui): adds beforeInput & afterInput props for arrays, `bloc…
Browse files Browse the repository at this point in the history
…ks`, `collapsible`, `group`, `radio`, & `relationship` fields. (#9674)

The following fields did not have the ability to add beforeInput &
afterInput:
- Arrays
- Blocks
- Collapsibles
- Groups
- Radios
- Relationships

### How?

Adds the ability to define and add before and after inputs to these
fields in your config.

Here are examples of the above fields with beforeInputs & afterInputs
defined (I.e. `#before-input` & `#after-input`):

`Arrays`:
![Screenshot 2024-12-02 at 1 22
15 PM](https://github.com/user-attachments/assets/8a2d5351-acab-4b28-b9bd-b19e1942da7e)


`Blocks`:
![Screenshot 2024-12-02 at 1 35
53 PM](https://github.com/user-attachments/assets/e9b5f22b-2671-4efb-8ee4-b4de3a1addc5)


`Collapsible`:
![Screenshot 2024-12-02 at 1 46
34 PM](https://github.com/user-attachments/assets/38f7a016-8a79-4ece-90d2-0b1761db19cd)


`Groups`:
![Screenshot 2024-12-02 at 1 52
34 PM](https://github.com/user-attachments/assets/dc6a123b-ee01-4021-bbbf-ac1b8c086072)


`Radios`:
![Screenshot 2024-12-02 at 1 59
35 PM](https://github.com/user-attachments/assets/4ddd16a1-2ad2-44f5-a7e9-86aa6e4e947b)


`Relationships`:
![Screenshot 2024-12-02 at 1 21
55 PM](https://github.com/user-attachments/assets/b4679baf-6157-41c9-8485-ca570be979d2)
  • Loading branch information
PatrikKozak authored Dec 2, 2024
1 parent 631edd4 commit 58b7415
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 8 deletions.
14 changes: 14 additions & 0 deletions packages/payload/src/fields/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ export type DateFieldClient = {
export type GroupField = {
admin?: {
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Label?: CustomComponent<GroupFieldLabelClientComponent | GroupFieldLabelServerComponent>
} & Admin['components']
hideGutter?: boolean
Expand Down Expand Up @@ -660,6 +662,8 @@ export type CollapsibleField = {
| {
admin: {
components: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Label: CustomComponent<
CollapsibleFieldLabelClientComponent | CollapsibleFieldLabelServerComponent
>
Expand All @@ -671,6 +675,8 @@ export type CollapsibleField = {
| {
admin?: {
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Label?: CustomComponent<
CollapsibleFieldLabelClientComponent | CollapsibleFieldLabelServerComponent
>
Expand Down Expand Up @@ -1029,6 +1035,8 @@ type RelationshipAdmin = {
allowCreate?: boolean
allowEdit?: boolean
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Error?: CustomComponent<
RelationshipFieldErrorClientComponent | RelationshipFieldErrorServerComponent
>
Expand Down Expand Up @@ -1124,6 +1132,8 @@ export type RichTextFieldClient<
export type ArrayField = {
admin?: {
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Error?: CustomComponent<ArrayFieldErrorClientComponent | ArrayFieldErrorServerComponent>
Label?: CustomComponent<ArrayFieldLabelClientComponent | ArrayFieldLabelServerComponent>
RowLabel?: RowLabelComponent
Expand Down Expand Up @@ -1163,6 +1173,8 @@ export type ArrayFieldClient = {
export type RadioField = {
admin?: {
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Error?: CustomComponent<RadioFieldErrorClientComponent | RadioFieldErrorServerComponent>
Label?: CustomComponent<RadioFieldLabelClientComponent | RadioFieldLabelServerComponent>
} & Admin['components']
Expand Down Expand Up @@ -1302,6 +1314,8 @@ export type ClientBlock = {
export type BlocksField = {
admin?: {
components?: {
afterInput?: CustomComponent[]
beforeInput?: CustomComponent[]
Error?: CustomComponent<BlocksFieldErrorClientComponent | BlocksFieldErrorServerComponent>
} & Admin['components']
initCollapsed?: boolean
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/fields/Array/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
)

const {
customComponents: { Description, Error, Label, RowLabels } = {},
customComponents: { AfterInput, BeforeInput, Description, Error, Label, RowLabels } = {},
errorPaths,
rows: rowsData = [],
showError,
Expand Down Expand Up @@ -268,6 +268,7 @@ export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
/>
</header>
<NullifyLocaleField fieldValue={value} localized={localized} path={path} />
{BeforeInput}
{(rowsData?.length > 0 || (!valid && (showRequired || showMinRows))) && (
<DraggableSortable
className={`${baseClass}__draggable-rows`}
Expand Down Expand Up @@ -349,6 +350,7 @@ export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
{t('fields:addLabel', { label: getTranslation(labels.singular, i18n) })}
</Button>
)}
{AfterInput}
</div>
)
}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/fields/Blocks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const BlocksFieldComponent: BlocksFieldClientComponent = (props) => {
)

const {
customComponents: { Description, Error, Label } = {},
customComponents: { AfterInput, BeforeInput, Description, Error, Label } = {},
errorPaths,
rows = [],
showError,
Expand Down Expand Up @@ -250,6 +250,7 @@ const BlocksFieldComponent: BlocksFieldClientComponent = (props) => {
Fallback={<FieldDescription description={description} path={path} />}
/>
</header>
{BeforeInput}
<NullifyLocaleField fieldValue={value} localized={localized} path={path} />
{(rows.length > 0 || (!valid && (showRequired || showMinRows))) && (
<DraggableSortable
Expand Down Expand Up @@ -350,6 +351,7 @@ const BlocksFieldComponent: BlocksFieldClientComponent = (props) => {
/>
</Fragment>
)}
{AfterInput}
</div>
)
}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/fields/Collapsible/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const CollapsibleFieldComponent: CollapsibleFieldClientComponent = (props) => {
const [errorCount, setErrorCount] = useState(0)
const fieldHasErrors = errorCount > 0

const { customComponents: { Description, Label } = {} } = useField({
const { customComponents: { AfterInput, BeforeInput, Description, Label } = {} } = useField({
path,
})

Expand Down Expand Up @@ -120,6 +120,7 @@ const CollapsibleFieldComponent: CollapsibleFieldClientComponent = (props) => {
id={`field-${fieldPreferencesKey}`}
style={styles}
>
{BeforeInput}
<CollapsibleElement
className={`${baseClass}__collapsible`}
collapsibleStyle={fieldHasErrors ? 'error' : 'default'}
Expand All @@ -142,6 +143,7 @@ const CollapsibleFieldComponent: CollapsibleFieldClientComponent = (props) => {
readOnly={readOnly}
/>
</CollapsibleElement>
{AfterInput}
<RenderCustomComponent
CustomComponent={Description}
Fallback={<FieldDescription description={description} path={path} />}
Expand Down
5 changes: 4 additions & 1 deletion packages/ui/src/fields/Group/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export const GroupFieldComponent: GroupFieldClientComponent = (props) => {
const isWithinGroup = useGroup()
const isWithinRow = useRow()
const isWithinTab = useTabs()
const { customComponents: { Description, Label } = {}, errorPaths } = useField({ path })
const { customComponents: { AfterInput, BeforeInput, Description, Label } = {}, errorPaths } =
useField({ path })
const submitted = useFormSubmitted()
const errorCount = errorPaths.length
const fieldHasErrors = submitted && errorCount > 0
Expand Down Expand Up @@ -94,6 +95,7 @@ export const GroupFieldComponent: GroupFieldClientComponent = (props) => {
)}
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
</div>
{BeforeInput}
<RenderFields
fields={fields}
margins="small"
Expand All @@ -105,6 +107,7 @@ export const GroupFieldComponent: GroupFieldClientComponent = (props) => {
/>
</div>
</GroupProvider>
{AfterInput}
</div>
)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/fields/Number/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ const NumberFieldComponent: NumberFieldClientComponent = (props) => {
CustomComponent={Error}
Fallback={<FieldError path={path} showError={showError} />}
/>
{BeforeInput}
{hasMany ? (
<ReactSelect
className={`field-${path.replace(/\./g, '__')}`}
Expand Down Expand Up @@ -177,7 +178,6 @@ const NumberFieldComponent: NumberFieldClientComponent = (props) => {
/>
) : (
<div>
{BeforeInput}
<input
disabled={readOnly}
id={`field-${path.replace(/\./g, '__')}`}
Expand All @@ -194,9 +194,9 @@ const NumberFieldComponent: NumberFieldClientComponent = (props) => {
type="number"
value={typeof value === 'number' ? value : ''}
/>
{AfterInput}
</div>
)}
{AfterInput}
<RenderCustomComponent
CustomComponent={Description}
Fallback={<FieldDescription description={description} path={path} />}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/fields/RadioGroup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const RadioGroupFieldComponent: RadioFieldClientComponent = (props) => {
)

const {
customComponents: { Description, Error, Label } = {},
customComponents: { AfterInput, BeforeInput, Description, Error, Label } = {},
setValue,
showError,
value: valueFromContext,
Expand Down Expand Up @@ -90,6 +90,7 @@ const RadioGroupFieldComponent: RadioFieldClientComponent = (props) => {
}
/>
<div className={`${fieldBaseClass}__wrap`}>
{BeforeInput}
<ul className={`${baseClass}--group`} id={`field-${path.replace(/\./g, '__')}`}>
{options.map((option) => {
let optionValue = ''
Expand Down Expand Up @@ -127,6 +128,7 @@ const RadioGroupFieldComponent: RadioFieldClientComponent = (props) => {
)
})}
</ul>
{AfterInput}
<RenderCustomComponent
CustomComponent={Description}
Fallback={<FieldDescription description={description} path={path} />}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/fields/Relationship/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
)

const {
customComponents: { Description, Error, Label } = {},
customComponents: { AfterInput, BeforeInput, Description, Error, Label } = {},
filterOptions,
initialValue,
setValue,
Expand Down Expand Up @@ -603,6 +603,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
CustomComponent={Error}
Fallback={<FieldError path={path} showError={showError} />}
/>
{BeforeInput}
{!errorLoading && (
<div className={`${baseClass}__wrap`}>
<ReactSelect
Expand Down Expand Up @@ -707,6 +708,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
</div>
)}
{errorLoading && <div className={`${baseClass}__error-loading`}>{errorLoading}</div>}
{AfterInput}
<RenderCustomComponent
CustomComponent={Description}
Fallback={<FieldDescription description={description} path={path} />}
Expand Down
114 changes: 114 additions & 0 deletions test/admin/collections/CustomFields/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,119 @@ export const CustomFields: CollectionConfig = {
},
},
},
{
name: 'relationshipFieldWithBeforeAfterInputs',
type: 'relationship',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
},
relationTo: 'posts',
},
{
name: 'arrayFieldWithBeforeAfterInputs',
type: 'array',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
},
fields: [
{
name: 'someTextField',
type: 'text',
},
],
},
{
name: 'blocksFieldWithBeforeAfterInputs',
type: 'blocks',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
},
blocks: [
{
slug: 'blockFields',
fields: [
{
name: 'textField',
type: 'text',
},
],
},
],
},
{
label: 'Collapsible Field With Before & After Inputs',
type: 'collapsible',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
description: 'This is a collapsible field.',
initCollapsed: false,
},
fields: [
{
name: 'text',
type: 'text',
},
],
},
{
name: 'groupFieldWithBeforeAfterInputs',
type: 'group',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
},
fields: [
{
name: 'textOne',
type: 'text',
},
{
name: 'textTwo',
type: 'text',
},
],
},
{
name: 'radioFieldWithBeforeAfterInputs',
label: {
en: 'Radio en',
es: 'Radio es',
},
type: 'radio',
admin: {
components: {
afterInput: ['/collections/CustomFields/AfterInput.js#AfterInput'],
beforeInput: ['/collections/CustomFields/BeforeInput.js#BeforeInput'],
},
},
options: [
{
label: { en: 'Value One', es: 'Value Uno' },
value: 'one',
},
{
label: 'Value Two',
value: 'two',
},
{
label: 'Value Three',
value: 'three',
},
],
},
],
}

0 comments on commit 58b7415

Please sign in to comment.