docs: adds examples of typed custom field components (#10741)
Although the "customizing fields" doc provides a big picture overview of how to create custom field components, it is not explicit enough for developers to know exactly where to start. For example, it can be challenging to import the correct types when building these components, and the natural place to go looking for this information is on the fields docs themselves. Now, each field doc has its own dedicated "custom components" section which provides concrete examples for fields and field labels in both server and client component format, with more examples to come over time such as using inputs directly, etc. In the same vein, the "customizing fields" doc itself should probably be moved to the fields overview section so it remains as intuitive as possible when searching for this information.
This commit is contained in:
@@ -125,18 +125,99 @@ export const ExampleCollection: CollectionConfig = {
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
admin: {
|
||||
components: {
|
||||
RowLabel: '/path/to/ArrayRowLabel#ArrayRowLabel',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Example of a custom RowLabel component
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { ArrayField } from '@payloadcms/ui'
|
||||
import type { ArrayFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomArrayFieldServer: ArrayFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions
|
||||
}) => {
|
||||
return (
|
||||
<ArrayField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { ArrayField } from '@payloadcms/ui'
|
||||
import type { ArrayFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomArrayFieldClient: ArrayFieldClientComponent = (props) => {
|
||||
return <ArrayField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { ArrayFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomArrayFieldLabelServer: ArrayFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import type { ArrayFieldLabelClientComponent } from 'payload'
|
||||
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const CustomArrayFieldLabelClient: ArrayFieldLabelClientComponent = ({
|
||||
field,
|
||||
path
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Row Label
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
@@ -209,6 +209,92 @@ export const ExampleCollection: CollectionConfig = {
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { BlocksField } from '@payloadcms/ui'
|
||||
import type { BlocksFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomBlocksFieldServer: BlocksFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions
|
||||
}) => {
|
||||
return (
|
||||
<BlocksField field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { BlocksField } from '@payloadcms/ui'
|
||||
import type { BlocksFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomBlocksFieldClient: BlocksFieldClientComponent = (props) => {
|
||||
return <BlocksField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { BlocksFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomBlocksFieldLabelServer: BlocksFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { BlocksFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomBlocksFieldLabelClient: BlocksFieldLabelClientComponent = ({
|
||||
label,
|
||||
path,
|
||||
required,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
As you build your own Block configs, you might want to store them in separate files but retain typing accordingly. To do so, you can import and use Payload's `Block` type:
|
||||
|
||||
@@ -67,3 +67,90 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { CheckboxField } from '@payloadcms/ui'
|
||||
import type { CheckboxFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomCheckboxFieldServer: CheckboxFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<CheckboxField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { CheckboxField } from '@payloadcms/ui'
|
||||
import type { CheckboxFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (props) => {
|
||||
return <CheckboxField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { CheckboxFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { CheckboxFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent = ({
|
||||
label,
|
||||
path,
|
||||
required,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -95,3 +95,85 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { CodeField } from '@payloadcms/ui'
|
||||
import type { CodeFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomCodeFieldServer: CodeFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<CodeField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { CodeField } from '@payloadcms/ui'
|
||||
import type { CodeFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomCodeFieldClient: CodeFieldClientComponent = (props) => {
|
||||
return <CodeField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { CodeFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomCodeFieldLabelServer: CodeFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { CodeFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomCodeFieldLabelClient: CodeFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -135,3 +135,90 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { DateTimeField } from '@payloadcms/ui'
|
||||
import type { DateFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomDateFieldServer: DateFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<DateTimeField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { DateTimeField } from '@payloadcms/ui'
|
||||
import type { DateFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomDateFieldClient: DateFieldClientComponent = (props) => {
|
||||
return <DateTimeField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { DateFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomDateFieldLabelServer: DateFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { DateFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomDateFieldLabelClient: DateFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -90,3 +90,83 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { EmailField } from '@payloadcms/ui'
|
||||
import type { EmailFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomEmailFieldServer: EmailFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<EmailField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { EmailField } from '@payloadcms/ui'
|
||||
import type { EmailFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomEmailFieldClient: EmailFieldClientComponent = (props) => {
|
||||
return <EmailField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { EmailFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomEmailFieldLabelServer: EmailFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { EmailFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomEmailFieldLabelClient: EmailFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)}
|
||||
```
|
||||
|
||||
@@ -154,3 +154,89 @@ export const ExampleCollection: CollectionConfig = {
|
||||
// {"foo": "bar"} or {"foo": "foobar"} - ok
|
||||
// Attempting to create {"foo": "not-bar"} will throw an error
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { JSONField } from '@payloadcms/ui'
|
||||
import type { JSONFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomJSONFieldServer: JSONFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<JSONField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { JSONField } from '@payloadcms/ui'
|
||||
import type { JSONFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomJSONFieldClient: JSONFieldClientComponent = (props) => {
|
||||
return <JSONField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { JSONFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomJSONFieldLabelServer: JSONFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { JSONFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomJSONFieldLabelClient: JSONFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -98,3 +98,89 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { NumberField } from '@payloadcms/ui'
|
||||
import type { NumberFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomNumberFieldServer: NumberFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<NumberField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { NumberField } from '@payloadcms/ui'
|
||||
import type { NumberFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomNumberFieldClient: NumberFieldClientComponent = (props) => {
|
||||
return <NumberField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { NumberFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomNumberFieldLabelServer: NumberFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { NumberFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomNumberFieldLabelClient: NumberFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -129,3 +129,84 @@ payload.find({
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { PointField } from '@payloadcms/ui'
|
||||
import type { PointFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomPointFieldServer: PointFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<PointField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { PointField } from '@payloadcms/ui'
|
||||
import type { PointFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomPointFieldClient: PointFieldClientComponent = (props) => {
|
||||
return <PointField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { PointFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomPointFieldLabelServer: PointFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { PointFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomPointFieldLabelClient: PointFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -117,3 +117,90 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { RadioGroupField } from '@payloadcms/ui'
|
||||
import type { RadioFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomRadioFieldServer: RadioFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<RadioGroupField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { RadioGroupField } from '@payloadcms/ui'
|
||||
import type { RadioFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomRadioFieldClient: RadioFieldClientComponent = (props) => {
|
||||
return <RadioGroupField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { RadioFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomRadioFieldLabelServer: RadioFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
required,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { RadioFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomRadioFieldLabelClient: RadioFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -373,3 +373,89 @@ Since we are referencing multiple collections, the field you are querying on may
|
||||
You **cannot** query on a field within a polymorphic relationship as you would with a
|
||||
non-polymorphic relationship.
|
||||
</Banner>
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { RelationshipField } from '@payloadcms/ui'
|
||||
import type { RelationshipFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomRelationshipFieldServer: RelationshipFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<RelationshipField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { RelationshipField } from '@payloadcms/ui'
|
||||
import type { RelationshipFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomRelationshipFieldClient: RelationshipFieldClientComponent = (props) => {
|
||||
return <RelationshipField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { RelationshipFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerComponent = (
|
||||
clientField,
|
||||
path
|
||||
) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { RelationshipFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -125,83 +125,90 @@ export const ExampleCollection: CollectionConfig = {
|
||||
}
|
||||
```
|
||||
|
||||
## Customization
|
||||
## Custom Components
|
||||
|
||||
The Select field UI component can be customized by providing a custom React component to the `components` object in the Base config.
|
||||
### Field
|
||||
|
||||
```ts
|
||||
export const CustomSelectField: Field = {
|
||||
name: 'customSelectField',
|
||||
type: 'select', // or 'text' if you have dynamic options
|
||||
admin: {
|
||||
components: {
|
||||
Field: CustomSelectComponent({
|
||||
options: [
|
||||
{
|
||||
label: 'Option 1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Option 2',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
#### Server Component
|
||||
|
||||
You can import the existing Select component directly from Payload, then extend and customize it as needed.
|
||||
```tsx
|
||||
import type { SelectFieldServerComponent } from 'payload'
|
||||
import type React from 'react'
|
||||
|
||||
```ts
|
||||
import * as React from 'react';
|
||||
import { SelectInput, useAuth, useField } from '@payloadcms/ui';
|
||||
|
||||
type CustomSelectProps = {
|
||||
path: string;
|
||||
options: {
|
||||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export const CustomSelectComponent: React.FC<CustomSelectProps> = ({ path, options }) => {
|
||||
const { value, setValue } = useField<string>({ path })
|
||||
const { user } = useAuth()
|
||||
|
||||
const adjustedOptions = options.filter((option) => {
|
||||
/*
|
||||
A common use case for a custom select
|
||||
is to show different options based on
|
||||
the current user's role.
|
||||
*/
|
||||
return option;
|
||||
});
|
||||
import { SelectField } from '@payloadcms/ui'
|
||||
|
||||
export const CustomSelectFieldServer: SelectFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<label className="field-label">
|
||||
Custom Select
|
||||
</label>
|
||||
<SelectInput
|
||||
path={path}
|
||||
name={path}
|
||||
options={adjustedOptions}
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.value)}
|
||||
/>
|
||||
</div>
|
||||
<SelectField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you are looking to create a dynamic select field, the following tutorial will walk you through the process of creating a custom select field that fetches its options from an external API.
|
||||
#### Client Component
|
||||
|
||||
<VideoDrawer
|
||||
id="Efn9OxSjA6Y"
|
||||
label="How to Create a Custom Select Field"
|
||||
drawerTitle="How to Create a Custom Select Field: A Step-by-Step Guide"
|
||||
/>
|
||||
```tsx
|
||||
'use client'
|
||||
import type { SelectFieldClientComponent } from 'payload'
|
||||
|
||||
If you want to learn more about custom components check out the [Admin > Custom Component](/docs/admin/fields) docs.
|
||||
import { SelectField } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const CustomSelectFieldClient: SelectFieldClientComponent = (props) => {
|
||||
return <SelectField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { SelectFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomSelectFieldLabelServer: SelectFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { SelectFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomSelectFieldLabelClient: SelectFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -95,3 +95,85 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { TextField } from '@payloadcms/ui'
|
||||
import type { TextFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomTextFieldServer: TextFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<TextField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { TextField } from '@payloadcms/ui'
|
||||
import type { TextFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomTextFieldClient: TextFieldClientComponent = (props) => {
|
||||
return <TextField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { TextFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomTextFieldLabelServer: TextFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
required,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { TextFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomTextFieldLabelClient: TextFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -93,3 +93,89 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import type React from 'react'
|
||||
import { TextareaField } from '@payloadcms/ui'
|
||||
import type { TextareaFieldServerComponent } from 'payload'
|
||||
|
||||
export const CustomTextareaFieldServer: TextareaFieldServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
schemaPath,
|
||||
permissions,
|
||||
}) => {
|
||||
return (
|
||||
<TextareaField
|
||||
field={clientField}
|
||||
path={path}
|
||||
schemaPath={schemaPath}
|
||||
permissions={permissions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { TextareaField } from '@payloadcms/ui'
|
||||
import type { TextareaFieldClientComponent } from 'payload'
|
||||
|
||||
export const CustomTextareaFieldClient: TextareaFieldClientComponent = (props) => {
|
||||
return <TextareaField {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### Label
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { TextareaFieldLabelServerComponent } from 'payload'
|
||||
|
||||
export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent = ({
|
||||
clientField,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={clientField?.label || clientField?.name}
|
||||
path={path}
|
||||
required={clientField?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { FieldLabel } from '@payloadcms/ui'
|
||||
import type { TextareaFieldLabelClientComponent } from 'payload'
|
||||
|
||||
export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent = ({
|
||||
field,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<FieldLabel
|
||||
label={field?.label || field?.name}
|
||||
path={path}
|
||||
required={field?.required}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user