obsidian/wiki/payloadcms/custom-components-edit-view.md
2026-05-15 15:13:56 +01:00

6.2 KiB

title aliases tags sources created updated
Custom Components — Edit View
edit-view-components
payload-edit-view
admin-edit-view-slots
payloadcms
admin
custom-components
edit-view
react
raw/custom-components__edit-view.md
2026-05-15 2026-05-15

Overview

The Edit View is where users view and edit individual Collection or Global documents in the Admin Panel. It hosts the form that submits data to the server, plus controls for saving, publishing, and previewing.

Two customization levels:

  • Full replacement — swap out the entire Edit View with a wiki/payloadcms/custom-views
  • Slot injection — override specific components (buttons, status, upload) without replacing the whole view

Full Edit View Replacement

Use admin.components.views.edit.default in buildConfig (global) or per-Collection/Global config:

// Global (all collections/globals share this)
buildConfig({
  admin: {
    components: {
      views: {
        edit: {
          default: { Component: '/path/to/MyCustomEditView' },
        },
      },
    },
  },
})

Props available: DocumentViewServerProps (server) / DocumentViewClientProps (client).

Custom Component Slots

Configured via admin.components.edit on Collection or Global config. Collections and Globals share the same key; Upload is Collection-only.

Slot Description
beforeDocumentControls Array — inject before Save/Publish buttons
editMenuItems Array — inject into 3-dot dropdown menu
SaveButton Replace default Save button
SaveDraftButton Replace Save Draft button (requires versions.drafts: true)
PublishButton Replace Publish button (requires versions.drafts: true)
UnpublishButton Replace Unpublish button (requires versions.drafts: true)
PreviewButton Replace Preview button (requires admin.preview on collection/global)
Status Replace draft/published status indicator
Upload Replace file upload UI (Collection only, requires upload: true)

Slot Examples

beforeDocumentControls

export const MyCollection: CollectionConfig = {
  admin: {
    components: {
      edit: {
        beforeDocumentControls: ['/path/to/CustomComponent'],
      },
    },
  },
}

Props: BeforeDocumentControlsServerProps / BeforeDocumentControlsClientProps

editMenuItems

Items appear below the default options (Create New, Duplicate, Delete). Use PopupList.Button from @payloadcms/ui to match default dropdown styles.

export const Pages: CollectionConfig = {
  admin: {
    components: {
      edit: {
        editMenuItems: ['/path/to/CustomEditMenuItem'],
      },
    },
  },
}
// Client component using built-in styling
'use client'
import { PopupList } from '@payloadcms/ui'
import type { EditMenuItemsClientProps } from 'payload'

export const EditMenuItems = (props: EditMenuItemsClientProps) => (
  <PopupList.ButtonGroup>
    <PopupList.Button onClick={() => {}}>Custom Action</PopupList.Button>
  </PopupList.ButtonGroup>
)

SaveButton / SaveDraftButton / PublishButton / UnpublishButton

All follow the same pattern — import the built-in component from @payloadcms/ui and wrap/extend it:

import { SaveButton } from '@payloadcms/ui'
import type { SaveButtonServerProps } from 'payload'

export function MySaveButton(props: SaveButtonServerProps) {
  return <SaveButton label="Save" />
}

PreviewButton

Requires admin.preview to be set on the collection/global:

export const Posts: CollectionConfig = {
  admin: {
    preview: () => 'https://example.com/preview',
    components: {
      edit: { PreviewButton: '/path/to/CustomPreviewButton' },
    },
  },
}

Upload (Collection-only)

Custom upload components must integrate with Payload's form system — a plain <input type="file" /> won't work. Use <Upload> from @payloadcms/ui with useDocumentInfo():

'use client'
import { Upload, useDocumentInfo } from '@payloadcms/ui'

export const CustomUploadClient = () => {
  const { collectionSlug, docConfig, initialState } = useDocumentInfo()
  return (
    <Upload
      collectionSlug={collectionSlug}
      initialState={initialState}
      uploadConfig={'upload' in docConfig ? docConfig.upload : undefined}
    />
  )
}

Description

Shared between Edit View and List View. Set at admin.components.Description (not under edit):

admin: {
  components: {
    Description: '/path/to/MyDescriptionComponent',
  },
}

Props: ViewDescriptionServerProps / ViewDescriptionClientProps

Key Takeaways

  • Two levels: full view replacement (views.edit.default) vs slot injection (components.edit.*)
  • Collections and Globals share admin.components.edit slots — Upload is the only Collection-exclusive slot
  • Draft/publish buttons only render when versions.drafts: true is set; customizing them requires the same flag
  • PreviewButton only renders when admin.preview is defined on the entity
  • Upload custom components must use Payload's form system (useDocumentInfo + <Upload> from @payloadcms/ui) — raw <input type="file"> breaks integration
  • editMenuItems — use PopupList.Button for automatic style matching; pass className or plain <button> for custom styles
  • beforeDocumentControls accepts an array — multiple components inject in order
  • Server and Client component variants available for all slots; use 'use client' directive for client-side interactivity

Sources