Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add filterTooltipValueFn option to transform the value of the filter tooltip #360

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,17 @@ export const columnOptions: ColumnOption[] = [
required: false,
type: 'MRT_FilterFn',
},
{
columnOption: 'filterTooltipValueFn',
defaultValue: '',
description:
'Specify to transform tooltip values to a readable format.',
link: '',
linkText: '',
source: 'MRT',
required: false,
type: "(value: any) => string",
},
{
columnOption: 'filterVariant',
defaultValue: "'text'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData>({
columnDef._filterFn,
);
const currentFilterOption = columnDef._filterFn;
const filterValueFn =
columnDef.filterTooltipValueFn || ((value: any) => value as string);
const filterTooltip =
columnFilterDisplayMode === 'popover' && !isFilterActive
? localization.filterByColumn?.replace(
Expand All @@ -69,10 +71,12 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData>({
'{filterValue}',
`"${
Array.isArray(column.getFilterValue())
? (column.getFilterValue() as [string, string]).join(
? (column.getFilterValue() as [])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure here about the type, if the previous type was casted as [string, string] then it should remain so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since filterTooltipValueFn does the conversion to string, I think the input to filterTooltipValueFn should remain the original data type.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok yeah agree, do you think you could type the prop accordingly then? Basically, I´d like to avoid using any when possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a type definition. What do you think of this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @yamadayutaka could please add it to the prop? So it'd be filterToolValueFn?: (value: string) => string

.map((v) => filterValueFn(v))
.join(
`" ${isRangeFilter ? localization.and : localization.or} "`,
)
: (column.getFilterValue() as string)
: filterValueFn(column.getFilterValue())
}"`,
)
.replace('" "', '');
Expand Down
1 change: 1 addition & 0 deletions packages/mantine-react-table/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ export type MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown> = Omit<
enableEditing?: ((row: MRT_Row<TData>) => boolean) | boolean;
enableFilterMatchHighlighting?: boolean;
filterFn?: MRT_FilterFn<TData>;
filterTooltipValueFn?: (value: any) => string,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

filterVariant?:
| 'autocomplete'
| 'checkbox'
Expand Down
130 changes: 129 additions & 1 deletion packages/mantine-react-table/stories/features/Filtering.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { Button, Flex } from '@mantine/core';
import { Button, Checkbox, Flex, Group, SegmentedControl } from '@mantine/core';
import {
type MRT_ColumnDef,
type MRT_ColumnFiltersState,
Expand All @@ -8,6 +8,17 @@ import {
import { faker } from '@faker-js/faker';
import { type Meta } from '@storybook/react';

import { MRT_Localization_EN } from '../../src/locales/en';
import { MRT_Localization_JA } from '../../src/locales/ja';

import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(isBetween);
dayjs.extend(localizedFormat);
import Dayjs_EN from 'dayjs/locale/en';
import Dayjs_JA from 'dayjs/locale/ja';

const meta: Meta = {
title: 'Features/Filtering Examples',
};
Expand Down Expand Up @@ -730,3 +741,120 @@ export const ExternalSetFilterValue = () => (
)}
/>
);

export const CustomTooltipValueFn = () => {
const [localization, setLocalization] = useState(MRT_Localization_EN);
const [locale, setLocale] = useState<string | undefined>('en');
const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
[],
);
const [isActiveValueFn, setIsActiveValueFn] = useState<any>(undefined);
const [dateValueFn, setDateValueFn] = useState<any>(undefined);
const [enableValueFns, setEnableValueFns] = useState(true);

const formatDate = (date: any, format: string) => {
const d = dayjs(date || '');
return d.isValid() ? d.format(format) : '';
};
const formatIsActiveValue = () => (value: any) =>
value === 'true' ? 'Yes' : 'No';
const formatDateValue = () => (value: any) => formatDate(value, 'L');

useEffect(() => {
switch (locale) {
case 'en':
setLocalization(MRT_Localization_EN);
dayjs.locale(Dayjs_EN);
break;
case 'ja':
setLocalization(MRT_Localization_JA);
dayjs.locale(Dayjs_JA);
break;
}
}, [locale]);

useEffect(() => {
if (enableValueFns) {
setIsActiveValueFn(formatIsActiveValue);
setDateValueFn(formatDateValue);
} else {
setIsActiveValueFn(undefined);
setDateValueFn(undefined);
}
}, [enableValueFns]);

return (
<>
<MantineReactTable
renderTopToolbarCustomActions={() => (
<Group>
<Checkbox
label="Enable Custom Tooltip Value Fn"
checked={enableValueFns}
onChange={(event) =>
setEnableValueFns(event.currentTarget.checked)
}
/>
<SegmentedControl
data={['en', 'ja']}
value={locale}
onChange={setLocale}
/>
</Group>
)}
localization={localization}
columns={[
{
Cell: ({ cell }) => (cell.getValue() === 'true' ? 'Yes' : 'No'),
accessorFn: (originalRow) =>
originalRow.isActive ? 'true' : 'false',
filterVariant: 'checkbox',
filterTooltipValueFn: isActiveValueFn, //transform data to readable format for tooltip
header: 'Is Active',
id: 'isActive',
size: 200,
},
{
accessorKey: 'firstName',
header: 'First Name',
},
{
accessorKey: 'lastName',
header: 'Last Name',
},
{
Cell: ({ cell }) => formatDate(cell.getValue<Date>(), 'L'), //transform data to readable format for cell render
mantineFilterDateInputProps: {
locale: locale,
valueFormat: 'L',
},
accessorFn: (row) => new Date(row.birthDate), //transform data before processing so sorting works
accessorKey: 'birthDate',
filterVariant: 'date',
filterTooltipValueFn: dateValueFn, //transform data to readable format for tooltip
header: 'Birth Date (date)',
sortingFn: 'datetime',
},
{
Cell: ({ cell }) => formatDate(cell.getValue<Date>(), 'L'), //transform data to readable format for cell render
mantineFilterDateInputProps: {
locale: locale,
valueFormat: 'L',
},
accessorFn: (row) => new Date(row.birthDate), //transform data before processing so sorting works
accessorKey: 'birthDateRange',
filterVariant: 'date-range',
filterTooltipValueFn: dateValueFn, //transform data to readable format for tooltip
header: 'Birth Date (date-range)',
sortingFn: 'datetime',
},
]}
data={data}
onColumnFiltersChange={setColumnFilters}
state={{
columnFilters,
}}
/>
</>
);
};