我正在构建一个简单的预算跟踪器,我想让用户按应用程序名称进行过滤。
下面是我的代码。
[
{
"status": "on",
"id": "NZMwD83Nxg",
"name": "GTA_UA_UAC_Android_01_DAU",
"dailyBudget": 800,
"apps": [
{
"name": "app 1",
"icon": "https://marketing-0-7-0-85-220.png/230x0w.webp"
},
{
"name": "app 2",
"icon": "https://marketing-0-7-0-99-220.png/230x0w.webp"
}
],
"currency": "USD",
},
{
"status": "on",
"id": "aXly0x0vX6",
"name": "GTA_UA_UAC_Android_02_DAU",
"dailyBudget": 65,
"apps": [
{
"name": "app 3",
"icon": "https://marketing-0-7-0-85-220.png/230x0w.webp"
}
],
"currency": "USD",
}
]
这是我的专栏类型。
type AppsType = {
name: string;
icon: string;
};
export type MainCampaign = {
id: string;
name: string;
status: string;
apps: AppsType[];
dailyBudget: number;
currency: string;
};
export const columns: ColumnDef<MainCampaign>[] = [
{
accessorKey: "icon",
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Apps
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
),
cell: ({ row }) => {
const apps: AppsType[] = row.getValue("apps");
return (
<div style={{ display: "flex", gap: "10px" }}>
{apps.map((app, index) => (
<Avatar key={index}>
<AvatarImage src={app.icon} alt={app.name} />
<AvatarFallback>{app.name}</AvatarFallback>
</Avatar>
))}
</div>
);
},
},
{
accessorKey: "apps",
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
App Names
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
),
cell: ({ row }) => {
const apps: AppsType[] = row.getValue("apps");
return apps.map((app, index) => <div key={index}>{app.name}</div>);
},
},
{
accessorKey: "name",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Campaign Name
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
},
...
]
这是我现在在数据表中的输入,使用
apps
时有效,输入后没有结果。
<div className="flex items-center py-4">
<Input
id="filter-app"
placeholder="Filter App..."
value={table.getColumn("apps")?.getFilterValue()?.toString() ?? ""}
onChange={(event) =>
table.getColumn("apps")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
</div>
我已经记录了应用程序名称,结果如下所示:[“app1”,“app2”],[“app3”]。我最初的想法是检查它们是否包含过滤器值,然后返回字符串,但是在实现该功能时我遇到了困难。
非常感谢您的指导。
我已经解决了这个问题,下面是我的实现。
{
accessorKey: "apps",
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
App Names
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
),
cell: ({ row }) => {
const apps: AppsType[] = row.getValue("apps");
return apps.map((app, index) => <div key={index}>{app.name}</div>);
},
filterFn: (
row: Row<MainCampaign>,
_cloumnId: string,
filterValue: string
) => {
const apps: AppsType[] = row.getValue("apps");
return apps.some((app) =>
app.name.toLowerCase().includes(filterValue.toLowerCase())
);
},
},
这是我的数据表
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
onColumnFiltersChange: setColumnFilters,
getFilteredRowModel: getFilteredRowModel(),
onPaginationChange: setPagination,
filterFns: {
apps: (row, _columnId, value) => {
const apps: AppsType[] = row.getValue("apps");
const appsNameArr: string[] = apps.map((app) => app.name.toLowerCase());
return appsNameArr.some((name) => name.toLowerCase().includes(value));
},
},
state: {
sorting,
columnFilters,
pagination,
},
});
我做了一些清理工作,在 util.ts 中提取了我的过滤器函数
所以会是这样的。
{
accessorKey: "apps",
header: ({ column }) => (
...
),
cell: ({ row }) => {
...
},
filterFn: customFilterFn,
},
// data-table.tsx
const table = useReactTable({
data,
...
filterFns: {
apps: customFilterFn,
},
state: {
...
},
});