diff --git a/packages/ui/src/fields/Relationship/Input.tsx b/packages/ui/src/fields/Relationship/Input.tsx index 328bfc2e8..0792911cd 100644 --- a/packages/ui/src/fields/Relationship/Input.tsx +++ b/packages/ui/src/fields/Relationship/Input.tsx @@ -49,6 +49,7 @@ export const RelationshipInput: React.FC = (props) => { Description, Error, filterOptions, + formatDisplayedOptions, hasMany, initialValue, isSortable = true, @@ -100,9 +101,6 @@ export const RelationshipInput: React.FC = (props) => { const [options, dispatchOptions] = useReducer(optionsReducer, []) const valueRef = useRef(value) - // the line below seems odd - - valueRef.current = value const [DocumentDrawer, , { isDrawerOpen, openDrawer }] = useDocumentDrawer({ id: currentlyOpenRelationship.id, @@ -474,11 +472,7 @@ export const RelationshipInput: React.FC = (props) => { const docID = args.doc.id if (hasMany) { - const currentValue = valueRef.current - ? Array.isArray(valueRef.current) - ? valueRef.current - : [valueRef.current] - : [] + const currentValue = value ? (Array.isArray(value) ? value : [value]) : [] const valuesToSet = currentValue.map((option: ValueWithRelation) => { return { @@ -492,7 +486,7 @@ export const RelationshipInput: React.FC = (props) => { onChange({ relationTo: args.collectionConfig.slug, value: docID }) } }, - [i18n, config, hasMany, onChange], + [i18n, config, hasMany, onChange, value], ) const onDuplicate = useCallback( @@ -508,8 +502,8 @@ export const RelationshipInput: React.FC = (props) => { if (hasMany) { onChange( - valueRef.current - ? (valueRef.current as ValueWithRelation[]).concat({ + value + ? value.concat({ relationTo: args.collectionConfig.slug, value: args.doc.id, }) @@ -522,7 +516,7 @@ export const RelationshipInput: React.FC = (props) => { }) } }, - [i18n, config, hasMany, onChange], + [i18n, config, hasMany, onChange, value], ) const onDelete = useCallback( @@ -537,8 +531,8 @@ export const RelationshipInput: React.FC = (props) => { if (hasMany) { onChange( - valueRef.current - ? (valueRef.current as ValueWithRelation[]).filter((option) => { + value + ? value.filter((option) => { return option.value !== args.id }) : null, @@ -549,7 +543,7 @@ export const RelationshipInput: React.FC = (props) => { return }, - [i18n, config, hasMany, onChange], + [i18n, config, hasMany, onChange, value], ) const filterOption = useCallback((item: Option, searchFilter: string) => { @@ -671,6 +665,12 @@ export const RelationshipInput: React.FC = (props) => { } }, [openDrawer, currentlyOpenRelationship]) + useEffect(() => { + // needed to sync the ref value when other fields influence the value + // i.e. when a drawer is opened and the value is set + valueRef.current = value + }, [value]) + const valueToRender = findOptionsByValue({ allowEdit, options, value }) if (!Array.isArray(valueToRender) && valueToRender?.value === 'null') { @@ -742,14 +742,18 @@ export const RelationshipInput: React.FC = (props) => { ? (selected) => { if (hasMany) { if (selected === null) { + valueRef.current = [] onChange([]) } else { + valueRef.current = selected as ValueWithRelation[] onChange(selected as ValueWithRelation[]) } } else if (hasMany === false) { if (selected === null) { + valueRef.current = null onChange(null) } else { + valueRef.current = selected as ValueWithRelation onChange(selected as ValueWithRelation) } } @@ -822,7 +826,11 @@ export const RelationshipInput: React.FC = (props) => { }), }) }} - options={options} + options={ + typeof formatDisplayedOptions === 'function' + ? formatDisplayedOptions(options) + : options + } placeholder={placeholder} showError={showError} value={valueToRender ?? null} diff --git a/packages/ui/src/fields/Relationship/index.tsx b/packages/ui/src/fields/Relationship/index.tsx index a4b4f6dd0..d226727df 100644 --- a/packages/ui/src/fields/Relationship/index.tsx +++ b/packages/ui/src/fields/Relationship/index.tsx @@ -196,6 +196,9 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) => description={description} Error={Error} filterOptions={filterOptions} + formatDisplayedOptions={ + isPolymorphic ? undefined : (options) => options.map((opt) => opt.options).flat() + } isSortable={isSortable} Label={Label} label={label} diff --git a/packages/ui/src/fields/Relationship/types.ts b/packages/ui/src/fields/Relationship/types.ts index 98c7500cf..cf48acfa7 100644 --- a/packages/ui/src/fields/Relationship/types.ts +++ b/packages/ui/src/fields/Relationship/types.ts @@ -100,6 +100,7 @@ export type RelationshipInputProps = { readonly description?: StaticDescription readonly Error?: React.ReactNode readonly filterOptions?: FilterOptionsResult + readonly formatDisplayedOptions?: (options: OptionGroup[]) => Option[] | OptionGroup[] readonly isSortable?: boolean readonly Label?: React.ReactNode readonly label?: StaticLabel diff --git a/test/lexical/collections/Lexical/e2e/blocks/e2e.spec.ts b/test/lexical/collections/Lexical/e2e/blocks/e2e.spec.ts index 772faf68b..c12b4264a 100644 --- a/test/lexical/collections/Lexical/e2e/blocks/e2e.spec.ts +++ b/test/lexical/collections/Lexical/e2e/blocks/e2e.spec.ts @@ -240,7 +240,7 @@ describe('lexicalBlocks', () => { ) await dependsOnDocData.locator('.rs__control').click() - await expect(newBlock.locator('.rs__menu')).toHaveText('Text Fieldsinvalid') + await expect(newBlock.locator('.rs__menu')).toHaveText('invalid') await dependsOnDocData.locator('.rs__control').click() await dependsOnSiblingData.locator('.rs__control').click() @@ -281,7 +281,7 @@ describe('lexicalBlocks', () => { await dependsOnDocData.locator('.rs__control').click() await dependsOnSiblingData.locator('.rs__control').click() - await expect(newBlock.locator('.rs__menu')).toHaveText('Text Fieldsinvalid') + await expect(newBlock.locator('.rs__menu')).toHaveText('invalid') await dependsOnSiblingData.locator('.rs__control').click() await dependsOnBlockData.locator('.rs__control').click() @@ -322,7 +322,7 @@ describe('lexicalBlocks', () => { await dependsOnSiblingData.locator('.rs__control').click() await dependsOnBlockData.locator('.rs__control').click() - await expect(newBlock.locator('.rs__menu')).toHaveText('Text Fieldsinvalid') + await expect(newBlock.locator('.rs__menu')).toHaveText('invalid') await dependsOnBlockData.locator('.rs__control').click() await saveDocAndAssert(page)