Skip to content

Commit 220a18f

Browse files
authored
fix(ui): equals filter shows no results when value is cleared (#14673)
### What? Fixes a bug where clearing the value of an 'equals' filter in the collection list view would show no results (or only documents with empty string values) instead of showing all documents. ### Why? When a user cleared a filter value using backspace or delete, the WhereBuilder was converting the `null` value to an empty string `''`. This caused the query to become `equals=''`, which filtered for documents where the field equals an empty string, rather than treating it as "no filter" and showing all documents. This was inconsistent with the initial behavior when a filter is first added without a value, where all documents are displayed. ### How? Updated the `updateValue` function to pass `undefined` instead of an empty string when the debounced value is `null` or empty: ```typescript value: debouncedValue === null || debouncedValue === '' ? undefined : debouncedValue, ``` Fixes #14627
1 parent af6ba86 commit 220a18f

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

packages/ui/src/elements/WhereBuilder/Condition/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ export const Condition: React.FC<Props> = (props) => {
7474
valueOptions = reducedField.field.options
7575
}
7676

77-
const updateValue = useEffectEvent(async (debouncedValue) => {
77+
const updateValue = useEffectEvent(async (debouncedValue: Value) => {
7878
if (operator) {
7979
await updateCondition({
8080
type: 'value',
8181
andIndex,
8282
field: reducedField,
8383
operator,
8484
orIndex,
85-
value: debouncedValue === null ? '' : debouncedValue,
85+
value: debouncedValue === null || debouncedValue === '' ? undefined : debouncedValue,
8686
})
8787
}
8888
})

test/admin/e2e/list-view/e2e.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,33 @@ describe('List View', () => {
742742
await expect(valueInput).toHaveValue('Test')
743743
})
744744

745+
test('should show all documents when equals filter value is cleared', async () => {
746+
await page.goto(postsUrl.list)
747+
748+
await expect(page.locator(tableRowLocator)).toHaveCount(2)
749+
750+
const { whereBuilder } = await addListFilter({
751+
page,
752+
fieldLabel: 'Title',
753+
operatorLabel: 'equals',
754+
value: 'post1',
755+
})
756+
757+
// Wait for filter to be applied
758+
await page.waitForTimeout(500)
759+
760+
await expect(page.locator(tableRowLocator)).toHaveCount(1)
761+
762+
const valueInput = whereBuilder.locator('.condition__value >> input')
763+
await valueInput.clear()
764+
765+
// Wait for debounce
766+
await page.waitForTimeout(500)
767+
768+
// Should now show all 2 posts again (not 0 posts)
769+
await expect(page.locator(tableRowLocator)).toHaveCount(2)
770+
})
771+
745772
test('should still show second filter if two filters exist and first filter is removed', async () => {
746773
await page.goto(postsUrl.list)
747774

test/admin/payload-types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export interface Config {
9898
'list-view-select-api': ListViewSelectApi;
9999
virtuals: Virtual;
100100
'no-timestamps': NoTimestamp;
101+
'payload-kv': PayloadKv;
101102
'payload-locked-documents': PayloadLockedDocument;
102103
'payload-preferences': PayloadPreference;
103104
'payload-migrations': PayloadMigration;
@@ -135,13 +136,15 @@ export interface Config {
135136
'list-view-select-api': ListViewSelectApiSelect<false> | ListViewSelectApiSelect<true>;
136137
virtuals: VirtualsSelect<false> | VirtualsSelect<true>;
137138
'no-timestamps': NoTimestampsSelect<false> | NoTimestampsSelect<true>;
139+
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
138140
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
139141
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
140142
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
141143
};
142144
db: {
143145
defaultIDType: string;
144146
};
147+
fallbackLocale: ('false' | 'none' | 'null') | false | null | ('es' | 'en') | ('es' | 'en')[];
145148
globals: {
146149
'hidden-global': HiddenGlobal;
147150
'not-in-view-global': NotInViewGlobal;
@@ -637,6 +640,23 @@ export interface NoTimestamp {
637640
id: string;
638641
title?: string | null;
639642
}
643+
/**
644+
* This interface was referenced by `Config`'s JSON-Schema
645+
* via the `definition` "payload-kv".
646+
*/
647+
export interface PayloadKv {
648+
id: string;
649+
key: string;
650+
data:
651+
| {
652+
[k: string]: unknown;
653+
}
654+
| unknown[]
655+
| string
656+
| number
657+
| boolean
658+
| null;
659+
}
640660
/**
641661
* This interface was referenced by `Config`'s JSON-Schema
642662
* via the `definition` "payload-locked-documents".
@@ -1227,6 +1247,14 @@ export interface VirtualsSelect<T extends boolean = true> {
12271247
export interface NoTimestampsSelect<T extends boolean = true> {
12281248
title?: T;
12291249
}
1250+
/**
1251+
* This interface was referenced by `Config`'s JSON-Schema
1252+
* via the `definition` "payload-kv_select".
1253+
*/
1254+
export interface PayloadKvSelect<T extends boolean = true> {
1255+
key?: T;
1256+
data?: T;
1257+
}
12301258
/**
12311259
* This interface was referenced by `Config`'s JSON-Schema
12321260
* via the `definition` "payload-locked-documents_select".

0 commit comments

Comments
 (0)