Skip to content

Commit 23580b7

Browse files
Merge pull request #455 from KevinVandy/453-mrt_filtertextinput-crash-when-filter-type-is-multi-select-and-clear-empty-pill
fix: check filter type before clearing
2 parents 56b022a + dd88002 commit 23580b7

File tree

2 files changed

+128
-102
lines changed

2 files changed

+128
-102
lines changed

packages/mantine-react-table/src/components/inputs/MRT_FilterTextInput.tsx

+127-101
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,14 @@ export const MRT_FilterTextInput = <TData extends MRT_RowData>({
205205
}
206206
};
207207

208-
if (columnDef.Filter) {
209-
return (
210-
<>{columnDef.Filter?.({ column, header, rangeFilterIndex, table })}</>
211-
);
212-
}
213-
214208
const handleClearEmptyFilterChip = () => {
215-
setFilterValue('');
216-
column.setFilterValue(undefined);
209+
if (isMultiSelectFilter) {
210+
setFilterValue([]);
211+
column.setFilterValue([]);
212+
} else {
213+
setFilterValue('');
214+
column.setFilterValue(undefined);
215+
}
217216
setColumnFilterFns((prev) => ({
218217
...prev,
219218
[header.id]: allowedColumnFilterOptions?.[0] ?? 'fuzzy',
@@ -245,7 +244,8 @@ export const MRT_FilterTextInput = <TData extends MRT_RowData>({
245244
: textInputProps?.style),
246245
},
247246
title: filterPlaceholder,
248-
value: isMultiSelectFilter && !Array.isArray(filterValue) ? [] : filterValue,
247+
value:
248+
isMultiSelectFilter && !Array.isArray(filterValue) ? [] : filterValue,
249249
variant: 'unstyled',
250250
} as const;
251251

@@ -262,103 +262,129 @@ export const MRT_FilterTextInput = <TData extends MRT_RowData>({
262262
</ActionIcon>
263263
) : null;
264264

265-
return filterChipLabel ? (
266-
<Box style={commonProps.style}>
267-
<Badge
268-
className={classes['filter-chip-badge']}
269-
onClick={handleClearEmptyFilterChip}
270-
rightSection={ClearButton}
271-
size="lg"
272-
>
273-
{filterChipLabel}
274-
</Badge>
275-
</Box>
276-
) : isMultiSelectFilter ? (
277-
<MultiSelect
278-
{...commonProps}
279-
searchable
280-
{...multiSelectProps}
281-
className={clsx(className, multiSelectProps.className)}
282-
data={filterSelectOptions}
283-
onChange={(value) => setFilterValue(value)}
284-
ref={(node) => {
285-
if (node) {
286-
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
287-
node;
288-
if (multiSelectProps.ref) {
289-
multiSelectProps.ref.current = node;
265+
if (columnDef.Filter) {
266+
return (
267+
<>{columnDef.Filter?.({ column, header, rangeFilterIndex, table })}</>
268+
);
269+
}
270+
271+
if (filterChipLabel) {
272+
return (
273+
<Box style={commonProps.style}>
274+
<Badge
275+
className={classes['filter-chip-badge']}
276+
onClick={handleClearEmptyFilterChip}
277+
rightSection={ClearButton}
278+
size="lg"
279+
>
280+
{filterChipLabel}
281+
</Badge>
282+
</Box>
283+
);
284+
}
285+
286+
if (isMultiSelectFilter) {
287+
return (
288+
<MultiSelect
289+
{...commonProps}
290+
searchable
291+
{...multiSelectProps}
292+
className={clsx(className, multiSelectProps.className)}
293+
data={filterSelectOptions}
294+
onChange={(value) => setFilterValue(value)}
295+
ref={(node) => {
296+
if (node) {
297+
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
298+
node;
299+
if (multiSelectProps.ref) {
300+
multiSelectProps.ref.current = node;
301+
}
290302
}
303+
}}
304+
rightSection={
305+
filterValue?.toString()?.length && multiSelectProps?.clearable
306+
? ClearButton
307+
: undefined
291308
}
292-
}}
293-
rightSection={
294-
filterValue?.toString()?.length && multiSelectProps?.clearable
295-
? ClearButton
296-
: undefined
297-
}
298-
style={commonProps.style}
299-
/>
300-
) : isSelectFilter ? (
301-
<Select
302-
{...commonProps}
303-
clearable
304-
searchable
305-
{...selectProps}
306-
className={clsx(className, selectProps.className)}
307-
clearButtonProps={{
308-
size: 'md',
309-
}}
310-
data={filterSelectOptions}
311-
ref={(node) => {
312-
if (node) {
313-
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
314-
node;
315-
if (selectProps.ref) {
316-
selectProps.ref.current = node;
309+
style={commonProps.style}
310+
/>
311+
);
312+
}
313+
314+
if (isSelectFilter) {
315+
return (
316+
<Select
317+
{...commonProps}
318+
clearable
319+
searchable
320+
{...selectProps}
321+
className={clsx(className, selectProps.className)}
322+
clearButtonProps={{
323+
size: 'md',
324+
}}
325+
data={filterSelectOptions}
326+
ref={(node) => {
327+
if (node) {
328+
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
329+
node;
330+
if (selectProps.ref) {
331+
selectProps.ref.current = node;
332+
}
317333
}
318-
}
319-
}}
320-
style={commonProps.style}
321-
/>
322-
) : isDateFilter ? (
323-
<DateInput
324-
{...commonProps}
325-
allowDeselect
326-
clearable
327-
popoverProps={{ withinPortal: columnFilterDisplayMode !== 'popover' }}
328-
{...dateInputProps}
329-
className={clsx(className, dateInputProps.className)}
330-
onChange={(event) => commonProps.onChange(event === null ? '' : event)}
331-
ref={(node) => {
332-
if (node) {
333-
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
334-
node;
335-
if (dateInputProps.ref) {
336-
dateInputProps.ref.current = node;
334+
}}
335+
style={commonProps.style}
336+
/>
337+
);
338+
}
339+
340+
if (isDateFilter) {
341+
return (
342+
<DateInput
343+
{...commonProps}
344+
allowDeselect
345+
clearable
346+
popoverProps={{ withinPortal: columnFilterDisplayMode !== 'popover' }}
347+
{...dateInputProps}
348+
className={clsx(className, dateInputProps.className)}
349+
onChange={(event) => commonProps.onChange(event === null ? '' : event)}
350+
ref={(node) => {
351+
if (node) {
352+
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
353+
node;
354+
if (dateInputProps.ref) {
355+
dateInputProps.ref.current = node;
356+
}
337357
}
338-
}
339-
}}
340-
style={commonProps.style}
341-
/>
342-
) : isAutoCompleteFilter ? (
343-
<Autocomplete
344-
{...commonProps}
345-
onChange={(value) => setFilterValue(value)}
346-
rightSection={filterValue?.toString()?.length ? ClearButton : undefined}
347-
{...autoCompleteProps}
348-
className={clsx(className, autoCompleteProps.className)}
349-
data={filterSelectOptions}
350-
ref={(node) => {
351-
if (node) {
352-
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
353-
node;
354-
if (autoCompleteProps.ref) {
355-
autoCompleteProps.ref.current = node;
358+
}}
359+
style={commonProps.style}
360+
/>
361+
);
362+
}
363+
364+
if (isAutoCompleteFilter) {
365+
return (
366+
<Autocomplete
367+
{...commonProps}
368+
onChange={(value) => setFilterValue(value)}
369+
rightSection={filterValue?.toString()?.length ? ClearButton : undefined}
370+
{...autoCompleteProps}
371+
className={clsx(className, autoCompleteProps.className)}
372+
data={filterSelectOptions}
373+
ref={(node) => {
374+
if (node) {
375+
filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
376+
node;
377+
if (autoCompleteProps.ref) {
378+
autoCompleteProps.ref.current = node;
379+
}
356380
}
357-
}
358-
}}
359-
style={commonProps.style}
360-
/>
361-
) : (
381+
}}
382+
style={commonProps.style}
383+
/>
384+
);
385+
}
386+
387+
return (
362388
<TextInput
363389
{...commonProps}
364390
onChange={(e) => setFilterValue(e.target.value)}

packages/mantine-react-table/stories/fixed-bugs/filtering.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const SwitchFromEmptyToEqualsArray = () => (
1919
accessorKey: 'state',
2020
header: 'State',
2121
filterVariant: 'multi-select',
22-
columnFilterModeOptions: ['equals', 'empty'],
22+
columnFilterModeOptions: ['equals', 'empty', 'notEmpty'],
2323
mantineFilterMultiSelectProps: {
2424
data: ["Wyoming", "Delaware", "South Dakota", "Vermont", "Rhode Island"]
2525
}

0 commit comments

Comments
 (0)