11'use client'
2- import type { FilterOptionsResult , PaginatedDocs , ValueWithRelation , Where } from 'payload'
2+ import type {
3+ DocumentEvent ,
4+ FilterOptionsResult ,
5+ PaginatedDocs ,
6+ ValueWithRelation ,
7+ Where ,
8+ } from 'payload'
39
410import { dequal } from 'dequal/lite'
511import { formatAdminURL , wordBoundariesRegex } from 'payload/shared'
@@ -24,15 +30,16 @@ import { useEffectEvent } from '../../hooks/useEffectEvent.js'
2430import { useQueue } from '../../hooks/useQueue.js'
2531import { useAuth } from '../../providers/Auth/index.js'
2632import { useConfig } from '../../providers/Config/index.js'
33+ import { useDocumentEvents } from '../../providers/DocumentEvents/index.js'
2734import { useLocale } from '../../providers/Locale/index.js'
2835import { useTranslation } from '../../providers/Translation/index.js'
2936import { sanitizeFilterOptionsQuery } from '../../utilities/sanitizeFilterOptionsQuery.js'
3037import { fieldBaseClass } from '../shared/index.js'
3138import { createRelationMap } from './createRelationMap.js'
3239import { findOptionsByValue } from './findOptionsByValue.js'
3340import { optionsReducer } from './optionsReducer.js'
34- import { MultiValueLabel } from './select-components/MultiValueLabel/index.js'
3541import './index.scss'
42+ import { MultiValueLabel } from './select-components/MultiValueLabel/index.js'
3643import { SingleValue } from './select-components/SingleValue/index.js'
3744
3845const baseClass = 'relationship'
@@ -102,7 +109,7 @@ export const RelationshipInput: React.FC<RelationshipInputProps> = (props) => {
102109
103110 const valueRef = useRef ( value )
104111
105- const [ DocumentDrawer , , { isDrawerOpen, openDrawer } ] = useDocumentDrawer ( {
112+ const [ DocumentDrawer , , { drawerSlug , isDrawerOpen, openDrawer } ] = useDocumentDrawer ( {
106113 id : currentlyOpenRelationship . id ,
107114 collectionSlug : currentlyOpenRelationship . collectionSlug ,
108115 } )
@@ -467,35 +474,75 @@ export const RelationshipInput: React.FC<RelationshipInputProps> = (props) => {
467474 } , Promise . resolve ( ) )
468475 } )
469476
470- const onSave = useCallback < DocumentDrawerProps [ 'onSave' ] > (
471- ( args ) => {
472- dispatchOptions ( {
473- type : 'UPDATE' ,
474- collection : args . collectionConfig ,
475- config,
476- doc : args . doc ,
477- i18n,
478- } )
477+ const { mostRecentUpdate } = useDocumentEvents ( )
479478
480- const docID = args . doc . id
479+ const handleDocumentUpdateEvent = useEffectEvent ( ( mostRecentUpdate : DocumentEvent ) => {
480+ if ( ! value ) {
481+ return false
482+ }
481483
482- if ( hasMany ) {
483- const currentValue = value ? ( Array . isArray ( value ) ? value : [ value ] ) : [ ]
484+ const docID = mostRecentUpdate . doc . id
484485
485- const valuesToSet = currentValue . map ( ( option : ValueWithRelation ) => {
486- return {
487- relationTo : option . value === docID ? args . collectionConfig . slug : option . relationTo ,
488- value : option . value ,
489- }
486+ let isMatchingUpdate = false
487+ if ( mostRecentUpdate . operation === 'update' ) {
488+ if ( hasMany === true ) {
489+ const currentValue = Array . isArray ( value ) ? value : [ value ]
490+ isMatchingUpdate = currentValue . some ( ( option ) => {
491+ return option . value === docID && option . relationTo === mostRecentUpdate . entitySlug
490492 } )
491-
492- onChange ( valuesToSet )
493493 } else if ( hasMany === false ) {
494- onChange ( { relationTo : args . collectionConfig . slug , value : docID } )
494+ isMatchingUpdate =
495+ value ?. value === docID && value ?. relationTo === mostRecentUpdate . entitySlug
495496 }
496- } ,
497- [ i18n , config , hasMany , onChange , value ] ,
498- )
497+ } else if ( mostRecentUpdate . operation === 'create' ) {
498+ // "Create New" drawer operations on the same level as this drawer should
499+ // set the value to the newly created document.
500+ // See test "should create document within document drawer > has one"
501+ isMatchingUpdate = mostRecentUpdate . drawerSlug === drawerSlug
502+ }
503+
504+ if ( ! isMatchingUpdate ) {
505+ return
506+ }
507+
508+ const collectionConfig = getEntityConfig ( { collectionSlug : mostRecentUpdate . entitySlug } )
509+
510+ dispatchOptions ( {
511+ type : 'UPDATE' ,
512+ collection : collectionConfig ,
513+ config,
514+ doc : mostRecentUpdate . doc ,
515+ i18n,
516+ } )
517+
518+ if ( hasMany ) {
519+ const currentValue = value ? ( Array . isArray ( value ) ? value : [ value ] ) : [ ]
520+
521+ const valuesToSet = currentValue . map ( ( option : ValueWithRelation ) => {
522+ return {
523+ relationTo : option . value === docID ? mostRecentUpdate . entitySlug : option . relationTo ,
524+ value : option . value ,
525+ }
526+ } )
527+
528+ onChange ( valuesToSet )
529+ } else if ( hasMany === false ) {
530+ onChange ( { relationTo : mostRecentUpdate . entitySlug , value : docID } )
531+ }
532+ } )
533+
534+ /**
535+ * Listen to document update events. If you edit a related document from a drawer and save it, this event
536+ * will be triggered. We then need up update the label of this relationship input, as the useAsLabel field could have changed.
537+ *
538+ * We listen to this event instead of using the onSave callback on the document drawer, as the onSave callback is not triggered
539+ * when you save a document from a drawer opened by a *different* relationship (or any other) field.
540+ */
541+ useEffect ( ( ) => {
542+ if ( mostRecentUpdate ) {
543+ handleDocumentUpdateEvent ( mostRecentUpdate )
544+ }
545+ } , [ mostRecentUpdate ] )
499546
500547 const onDuplicate = useCallback < DocumentDrawerProps [ 'onDuplicate' ] > (
501548 ( args ) => {
@@ -729,7 +776,6 @@ export const RelationshipInput: React.FC<RelationshipInputProps> = (props) => {
729776 disableKeyDown : isDrawerOpen || isListDrawerOpen ,
730777 disableMouseDown : isDrawerOpen || isListDrawerOpen ,
731778 onDocumentOpen,
732- onSave,
733779 } }
734780 disabled = { readOnly || isDrawerOpen || isListDrawerOpen }
735781 filterOption = { enableWordBoundarySearch ? filterOption : undefined }
@@ -870,7 +916,7 @@ export const RelationshipInput: React.FC<RelationshipInputProps> = (props) => {
870916 />
871917 </ div >
872918 { currentlyOpenRelationship . collectionSlug && currentlyOpenRelationship . hasReadPermission && (
873- < DocumentDrawer onDelete = { onDelete } onDuplicate = { onDuplicate } onSave = { onSave } />
919+ < DocumentDrawer onDelete = { onDelete } onDuplicate = { onDuplicate } />
874920 ) }
875921 { appearance === 'drawer' && ! readOnly && (
876922 < ListDrawer allowCreate = { allowCreate } enableRowSelections = { false } onSelect = { onListSelect } />
0 commit comments