fix(ui): relationship filter clearing on blur (#11021)

When using the filter controls in the list view on a relationship field,
the select options would clear after clicking outside of the component
then never repopulate. This caused the component to remain in an
unusable state, where no options would appear unless the filter is
completely removed and re-added. The reason for this is that the
`react-select` component fires an `onInputChange` event on blur, and the
handler that is subscribed to this event was unknowingly clearing the
options.

This PR also renames the various filter components, i.e.
`RelationshipField` -> `RelationshipFilter`. This improves semantics and
dedupes their names from the actual field components.

This bug was first introduced in this PR: #10553
This commit is contained in:
Jacob Fletcher
2025-02-06 15:27:34 -05:00
committed by GitHub
parent ae32c555ac
commit 8940726601
6 changed files with 21 additions and 22 deletions

View File

@@ -7,7 +7,7 @@ import { DatePickerField } from '../../../DatePicker/index.js'
const baseClass = 'condition-value-date'
export const DateField: React.FC<Props> = ({ disabled, field: { admin }, onChange, value }) => {
export const DateFilter: React.FC<Props> = ({ disabled, field: { admin }, onChange, value }) => {
const { date } = admin || {}
return (

View File

@@ -4,9 +4,9 @@ import React from 'react'
import type { FieldCondition } from '../../types.js'
import { DateField } from '../Date/index.js'
import { NumberField } from '../Number/index.js'
import { RelationshipField } from '../Relationship/index.js'
import { DateFilter } from '../Date/index.js'
import { NumberFilter } from '../Number/index.js'
import { RelationshipFilter } from '../Relationship/index.js'
import { Select } from '../Select/index.js'
import { Text } from '../Text/index.js'
@@ -45,7 +45,7 @@ export const DefaultFilter: React.FC<Props> = ({
switch (internalField?.field?.type) {
case 'date': {
return (
<DateField
<DateFilter
disabled={disabled}
field={internalField.field}
onChange={onChange}
@@ -57,7 +57,7 @@ export const DefaultFilter: React.FC<Props> = ({
case 'number': {
return (
<NumberField
<NumberFilter
disabled={disabled}
field={internalField.field}
onChange={onChange}
@@ -69,7 +69,7 @@ export const DefaultFilter: React.FC<Props> = ({
case 'relationship': {
return (
<RelationshipField
<RelationshipFilter
disabled={disabled}
field={internalField.field}
onChange={onChange}

View File

@@ -8,7 +8,7 @@ import './index.scss'
const baseClass = 'condition-value-number'
export const NumberField: React.FC<Props> = ({ disabled, onChange, value }) => {
export const NumberFilter: React.FC<Props> = ({ disabled, onChange, value }) => {
const { t } = useTranslation()
return (

View File

@@ -18,7 +18,7 @@ const baseClass = 'condition-value-relationship'
const maxResultsPerRequest = 10
export const RelationshipField: React.FC<Props> = (props) => {
export const RelationshipFilter: React.FC<Props> = (props) => {
const {
disabled,
field: { admin: { isSortable } = {}, hasMany, relationTo },
@@ -42,6 +42,7 @@ export const RelationshipField: React.FC<Props> = (props) => {
const debouncedSearch = useDebounce(search, 300)
const { i18n, t } = useTranslation()
const relationSlugs = hasMultipleRelations ? relationTo : [relationTo]
const initialRelationMap = () => {
const map: Map<string, number> = new Map()
relationSlugs.forEach((relation) => {
@@ -49,6 +50,7 @@ export const RelationshipField: React.FC<Props> = (props) => {
})
return map
}
const nextPageByRelationshipRef = React.useRef<Map<string, number>>(initialRelationMap())
const partiallyLoadedRelationshipSlugs = React.useRef<string[]>(relationSlugs)
@@ -205,11 +207,13 @@ export const RelationshipField: React.FC<Props> = (props) => {
}, [hasMany, hasMultipleRelations, value, options])
const handleInputChange = (input: string) => {
dispatchOptions({ type: 'CLEAR', i18n, required: false })
const relationSlug = partiallyLoadedRelationshipSlugs.current[0]
partiallyLoadedRelationshipSlugs.current = relationSlugs
nextPageByRelationshipRef.current.set(relationSlug, 1)
setSearch(input)
if (input !== search) {
dispatchOptions({ type: 'CLEAR', i18n, required: false })
const relationSlug = partiallyLoadedRelationshipSlugs.current[0]
partiallyLoadedRelationshipSlugs.current = relationSlugs
nextPageByRelationshipRef.current.set(relationSlug, 1)
setSearch(input)
}
}
const addOptionByID = useCallback(

View File

@@ -276,9 +276,9 @@ export { TranslationProvider, useTranslation } from '../../providers/Translation
export { useWindowInfo, WindowInfoProvider } from '../../providers/WindowInfo/index.js'
export { Text as TextCondition } from '../../elements/WhereBuilder/Condition/Text/index.js'
export { Select as SelectCondition } from '../../elements/WhereBuilder/Condition/Select/index.js'
export { RelationshipField as RelationshipCondition } from '../../elements/WhereBuilder/Condition/Relationship/index.js'
export { NumberField as NumberCondition } from '../../elements/WhereBuilder/Condition/Number/index.js'
export { DateField as DateCondition } from '../../elements/WhereBuilder/Condition/Date/index.js'
export { RelationshipFilter as RelationshipCondition } from '../../elements/WhereBuilder/Condition/Relationship/index.js'
export { NumberFilter as NumberCondition } from '../../elements/WhereBuilder/Condition/Number/index.js'
export { DateFilter as DateCondition } from '../../elements/WhereBuilder/Condition/Date/index.js'
export { EmailAndUsernameFields } from '../../elements/EmailAndUsername/index.js'
export { SelectAll } from '../../elements/SelectAll/index.js'
export { SelectRow } from '../../elements/SelectRow/index.js'

View File

@@ -118,10 +118,6 @@ export interface FieldsRelationship {
* This will filter the relationship options based on id, which is the same as the relationship field in this document
*/
relationshipFilteredByID?: (string | null) | RelationOne;
/**
* This will filter the relationship options if the filter field in this document is set to "Include me"
*/
relationshipFilteredByField?: (string | null) | RelationOne;
relationshipFilteredAsync?: (string | null) | RelationOne;
relationshipManyFiltered?:
| (
@@ -450,7 +446,6 @@ export interface FieldsRelationshipSelect<T extends boolean = true> {
relationshipRestricted?: T;
relationshipWithTitle?: T;
relationshipFilteredByID?: T;
relationshipFilteredByField?: T;
relationshipFilteredAsync?: T;
relationshipManyFiltered?: T;
filter?: T;