tanstack表:如何展开并显示一行中的各种数据,并且在单击操作按钮时不触发同一行中的所有可展开操作按钮

问题描述 投票:0回答:1

我希望每个操作按钮都有自己的可扩展独立行。我已经到了一半了。我正在使用 tanstack 表 v8。但问题是,如果我单击一行中的任何可扩展按钮,则会触发同一行中的所有可扩展按钮。我不想要这样。每个操作都会自行触发并用新数据扩展一行。 是否可以使用 tanstack 表或任何其他方式?

到目前为止我尝试过的一切都在这个codesandbox中。

reactjs react-table tanstack-table react-table-v8
1个回答
0
投票

我从未使用过 Tanstack...快速查看文档后,它似乎不支持多个扩展的东西。

我手动处理:https://codesandbox.io/p/sandbox/goofy-shtern-forked-3kny3x

基本上,这个想法是有一个状态来控制行/单元格的扩展方式。

expandedRowState
就是这么做的,它保存了行的id、展开的列以及展开的内容。当单击展开时,我不只是展开,而是使用该列进行了一些检查。

App.tsx

import "./styles.css";
import {
  ColumnDef,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  useReactTable,
} from "@tanstack/react-table";
import { useState } from "react";

import { expandableColumns, expandableData } from "./column-data";

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
  expandedRowContent: any;
  getRowCanExpand: (row: any) => boolean;
}

export function ExpandableTable<TData, TValue>({
  columns,
  data,
  expandedRowContent,
  getRowCanExpand,
}: DataTableProps<TData, TValue>) {
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});

  const table = useReactTable({
    data,
    columns,
    getRowCanExpand,
    state: {
      columnVisibility,
    },
    autoResetPageIndex: false,
    enableRowSelection: true,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getExpandedRowModel: getExpandedRowModel(),
  });

  return (
    <div className="space-y-4">
      <div className="rounded-md border">
        <table>
          <thead>
            {table.getHeaderGroups().map((headerGroup) => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map((header) => {
                  return (
                    <th key={header.id}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                    </th>
                  );
                })}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <>
                  <tr
                    key={row.id}
                    data-state={row.getIsSelected() && "selected"}
                  >
                    {row.getVisibleCells().map((cell) => (
                      <td key={cell.id}>
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext()
                        )}
                      </td>
                    ))}
                  </tr>

                  {row.getIsExpanded() && (
                    <tr>
                      {/* 2nd row is a custom 1 cell row */}
                      <td colSpan={row.getVisibleCells().length}>
                        {expandedRowContent[row.id].content}
                      </td>
                    </tr>
                  )}
                </>
              ))
            ) : (
              <tr>
                <td colSpan={columns.length} className="h-24 text-center">
                  No results.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

export default function App() {
  const [expandedRowState, setExpandedRowState] = useState<any>([]);

  const setExpandedRowStateById = (id: any, content: any, columnIndex: any) => {
    expandedRowState[id] = { content, columnIndex };
    setExpandedRowState([...expandedRowState]);
  };

  return (
    <div className="App">
      <h1>Expand Table Example</h1>
      <h2>Start editing to see some magic happen!</h2>
      <ExpandableTable
        data={expandableData}
        columns={expandableColumns(expandedRowState, setExpandedRowStateById)}
        expandedRowContent={expandedRowState}
        getRowCanExpand={() => true}
      />
    </div>
  );
}

列数据.tsx

export const expandableColumns = (expandedRowState: any, setExpandedRowState: any) => {
  return [
    {
      accessorKey: "firstName",
      header: "First Name",
      cell: ({ row, getValue }: any) => (
        <div
          style={{
            paddingLeft: `${row.depth * 2}rem`,
          }}
        >
          {row.getCanExpand() ? (
            <button
              {...{
                onClick: () => {
                  if (!row.getIsExpanded() || (row.getIsExpanded() && expandedRowState[row.id].columnIndex == 0)) {
                    row.getToggleExpandedHandler()();
                  }

                  setExpandedRowState(row.id, <p>FINGER EMOJI - {row.original.firstName}</p>, 0);
                },
                style: { cursor: "pointer" },
              }}
            >
              {row.getIsExpanded() && expandedRowState[row.id].columnIndex == 0 ? "👇" : "👉"}
            </button>
          ) : (
            "🔵"
          )}
          {getValue()}
        </div>
      ),
      footer: (props: { column: { id: any } }) => props.column.id,
    },
    {
      accessorFn: (row: { lastName: any }) => row.lastName,
      id: "lastName",
      cell: ({ row, getValue }: any) => (
        <div
          style={{
            paddingLeft: `${row.depth * 2}rem`,
          }}
        >
          {row.getCanExpand() ? (
            <button
              {...{
                onClick: () => {
                  if (!row.getIsExpanded() || (row.getIsExpanded() && expandedRowState[row.id].columnIndex == 1)) {
                    row.getToggleExpandedHandler()();
                  }

                  setExpandedRowState(row.id, <p>FLASHLIGHT EMOJI - {row.original.lastName}</p>, 1);
                },
                style: { cursor: "pointer" },
              }}
            >
              {row.getIsExpanded() && expandedRowState[row.id].columnIndex == 1 ? "♟" : "🔦"}
            </button>
          ) : (
            "🔵"
          )}
          {getValue()}
        </div>
      ),
      header: () => <span>Last Name</span>,
      footer: (props: { column: { id: any } }) => props.column.id,
    },
    {
      accessorKey: "age",
      header: () => "Age",
      footer: (props: { column: { id: any } }) => props.column.id,
    },
    {
      accessorKey: "visits",
      header: () => <span>Visits</span>,
      footer: (props: { column: { id: any } }) => props.column.id,
    },
    {
      accessorKey: "status",
      header: "Status",
      footer: (props: { column: { id: any } }) => props.column.id,
    },
    {
      accessorKey: "progress",
      header: "Profile Progress",
      footer: (props: { column: { id: any } }) => props.column.id,
    },
  ];
};

export const expandableData = [
  {
    firstName: "Marquis",
    lastName: "Runolfsdottir",
    age: 36,
    visits: 322,
    progress: 46,
    status: "single",
  },
  {
    firstName: "Hayden",
    lastName: "Ritchie",
    age: 35,
    visits: 208,
    progress: 79,
    status: "relationship",
  },
  {
    firstName: "Destany",
    lastName: "Boehm",
    age: 37,
    visits: 752,
    progress: 97,
    status: "relationship",
  },
  {
    firstName: "Kale",
    lastName: "Johnston",
    age: 36,
    visits: 378,
    progress: 13,
    status: "complicated",
  },
  {
    firstName: "Maybell",
    lastName: "Brown",
    age: 16,
    visits: 783,
    progress: 76,
    status: "complicated",
  },
  {
    firstName: "Emelia",
    lastName: "Cronin",
    age: 30,
    visits: 655,
    progress: 96,
    status: "complicated",
  },
  {
    firstName: "Kali",
    lastName: "Marvin",
    age: 18,
    visits: 926,
    progress: 57,
    status: "complicated",
  },
  {
    firstName: "Khalid",
    lastName: "Robel",
    age: 34,
    visits: 671,
    progress: 100,
    status: "complicated",
  },
  {
    firstName: "Zena",
    lastName: "Hilll",
    age: 34,
    visits: 934,
    progress: 18,
    status: "single",
  },
  {
    firstName: "Hiram",
    lastName: "Koss",
    age: 12,
    visits: 757,
    progress: 44,
    status: "relationship",
  },
];
© www.soinside.com 2019 - 2024. All rights reserved.