Back to Refine

Partial Use Table Relational Live Preview

documentation/docs/ui-integrations/ant-design/hooks/use-table/_partial-use-table-relational-live-preview.md

3.25.03.5 KB
Original Source
css
body {
  padding: 4px;
  background: white;
}
tsx
setInitialRoutes(["/posts"]);

// visible-block-start
import { HttpError, useMany } from "@refinedev/core";
import { getDefaultFilter } from "@refinedev/antd";

import {
  List,
  TagField,
  useTable,
  // highlight-start
  useSelect,
  FilterDropdown,
  // highlight-end
} from "@refinedev/antd";
import {
  Table,
  // highlight-next-line
  Select,
} from "antd";

// highlight-start
interface ICategory {
  id: number;
  title: string;
}
// highlight-end

interface IPost {
  id: number;
  title: string;
  content: string;
  status: "published" | "draft" | "rejected";
  // highlight-start
  category: {
    id: number;
  };
  // highlight-end
}

const PostList: React.FC = () => {
  const { tableProps, filters } = useTable<IPost, HttpError>();

  // highlight-start
  // Creates the array of ids. This will filter and fetch the category data for the relevant posts.
  const categoryIds =
    tableProps.dataSource?.map((p) => p.category.id.toString()) || [];
  // Fetches the category of each post. It uses the useMany hook to fetch the category data from the API.
  const { data, isFetching } = useMany<ICategory>({
    resource: "categories",
    ids: categoryIds,
    queryOptions: {
      // Set to true only if the posts array is not empty.
      enabled: categoryIds.length > 0,
    },
  });
  // highlight-end

  // highlight-start
  // Creates the props by needed the select component for filtering the posts by category.
  const { selectProps } = useSelect<ICategory>({
    resource: "categories",
    optionLabel: "title",
    optionValue: "id",
    defaultValue: getDefaultFilter("category.id", filters, "in"),
  });
  // highlight-end

  return (
    <List>
      <Table {...tableProps} rowKey="id">
        <Table.Column dataIndex="id" title="ID" />
        <Table.Column dataIndex="title" title="Title" />
        <Table.Column dataIndex="content" title="Content" />
        <Table.Column
          dataIndex={["category", "id"]}
          title="Category"
          render={(value) => {
            if (isFetching) return "loading...";
            // Gets the title of the category from the data object, which is the result of the useMany hook.
            return data?.data.find((p) => p.id === value)?.title;
          }}
          filterDropdown={(props: FilterDropdownProps) => (
            <FilterDropdown
              {...props}
              mapValue={(selectedKeys) =>
                selectedKeys.map((i) => parseInt(i.toString()))
              }
            >
              <Select
                style={{ minWidth: 200 }}
                mode="multiple"
                {...selectProps}
              />
            </FilterDropdown>
          )}
        />
        <Table.Column
          dataIndex="status"
          title="Status"
          render={(value: string) => <TagField value={value} />}
        />
      </Table>
    </List>
  );
};

// visible-block-end

render(
  <ReactRouter.BrowserRouter>
    <RefineAntdDemo
      resources={[
        {
          name: "posts",
          list: "/posts",
        },
      ]}
    >
      <ReactRouter.Routes>
        <ReactRouter.Route
          path="/posts"
          element={
            <div style={{ padding: 16 }}>
              <ReactRouter.Outlet />
            </div>
          }
        >
          <ReactRouter.Route index element={<PostList />} />
        </ReactRouter.Route>
      </ReactRouter.Routes>
    </RefineAntdDemo>
  </ReactRouter.BrowserRouter>,
);