Hatim Fayez
Hatim Fayez

Reputation: 231

Implementing React table expanded rows

It's my first time to use react-table librabry. I am struggling for the previous couple of days how to implement the expansion functionality using useExpanded hook

Docs and all the examples available are not clear about that so, here is my code and hope if somone can give me a hand in that

const accountData = [
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Oriana Hospital",
    accountType: "Hospital ",
    city: "Sharjah",
    area: "Al Khan",
    street: "Al Taawun",
    location: "https://goo.gl/maps/Jx6oTCbXyq9C8Mrt7",
    hasBranches: true,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 1,
    expand: false,
    branches: [
      {
        branchName: "Oriana Pulman ",
        branchType: "Hospital ",
        branchCity: "Sharjah",
        branchArea: "Sharjah",
        branchStreet: "Al Khan",
        branchLocation: "Al Taawun",
        _id: "622e2f05cc18e17eb608541a",
      },
    ],
    _id: "622e2f04cc18e17eb6085419",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Ajman Speciality",
    accountType: "Hospital ",
    city: "Ajman",
    area: "Ajman",
    street: "Al Ittihad Road",
    location: "https://goo.gl/maps/9aizJaNxT7iMDVry6",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2f05cc18e17eb608541b",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Al Ittihad Medical Center",
    accountType: "Clinic",
    city: "Ajman",
    area: "Al Swan",
    street: "Ittihad ",
    location: "https://goo.gl/maps/ppLNbPB9CdGWqFpy6",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2ff2a2c75bcb9aaf640e",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Al Zaora Medical Center",
    accountType: "Clinic",
    city: "Ajman",
    area: "Al Swan",
    street: "Ittihad ",
    location: "https://goo.gl/maps/PZr5PqFf28rpdgYJ7",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2ff2a2c75bcb9aaf640f",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Amina Hospital",
    accountType: "Hospital ",
    city: "Ajman",
    area: "Al Swan",
    street: "Ittihad ",
    location: "https://goo.gl/maps/Bxn7tedGQxUZFNqa8",
    hasBranches: true,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 3,
    expand: false,
    branches: [
      {
        branchName: "Ibn Sina ",
        branchType: "Clinic",
        branchCity: "Ajman",
        branchArea: "Al Swan",
        branchStreet: "Ittihad",
        branchLocation: "https://goo.gl/maps/M3WemaX4ehbp6rSS6",
        _id: "622e2ff2a2c75bcb9aaf6411",
      },
      {
        branchName: "Amina Al Jurf",
        branchType: "Clinic",
        branchCity: "Ajman",
        branchArea: "Al Jurf",
        branchStreet: "Sheikh Khalifa",
        branchLocation: "https://goo.gl/maps/VGgU5TGSBvaUnGqm6",
        _id: "622e2ff2a2c75bcb9aaf6412",
      },
      {
        branchName: "Family Medical Center",
        branchType: "Clinic",
        branchCity: "Ajman",
        branchArea: "Ajman",
        branchStreet: "Industiral Ajman",
        branchLocation: "https://goo.gl/maps/wvqTbtuRakzaYTWg7",
        _id: "622e2ff2a2c75bcb9aaf6413",
      },
    ],
    _id: "622e2ff2a2c75bcb9aaf6410",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Al Garhoud Private Hospital",
    accountType: "Hospital ",
    city: "Dubai",
    area: "Al Garhoud",
    street: "Reiyadh",
    location: "https://goo.gl/maps/LVpuJhMBT2MrobPT6",
    hasBranches: true,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 1,
    expand: false,
    branches: [
      {
        branchName: "Al Garhoud 2",
        branchType: "Hospital ",
        branchCity: "Dubai",
        branchArea: "Mirdif",
        branchStreet: "Sheikh Mohamed Bin Zayed",
        branchLocation: "https://goo.gl/maps/p2bKwpnBuLaH2yxS8",
        _id: "622e2ff2a2c75bcb9aaf6415",
      },
    ],
    _id: "622e2ff2a2c75bcb9aaf6414",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Emirates Hospital",
    accountType: "Hospital ",
    city: "Dubai",
    area: "Jumeirah",
    street: "Al Wasl",
    location: "https://goo.gl/maps/gqHVMFvhpnGgDCiL8",
    hasBranches: true,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 2,
    expand: false,
    branches: [
      {
        branchName: "Emirates Marina",
        branchType: "Hospital ",
        branchCity: "Dubai",
        branchArea: "Marina",
        branchStreet: "Marina",
        branchLocation: "https://goo.gl/maps/p2bKwpnBuLaH2yxS8",
        _id: "622e2ff2a2c75bcb9aaf6417",
      },
      {
        branchName: "Emirates Clinic",
        branchType: "Clinic",
        branchCity: "RAK",
        branchArea: "RAK",
        branchStreet: "Khalid street ",
        branchLocation: "https://goo.gl/maps/NMN68z5VqB9AoUKS7",
        _id: "622e2ff2a2c75bcb9aaf6418",
      },
    ],
    _id: "622e2ff2a2c75bcb9aaf6416",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Al Shams Medical Diagnsotice Center",
    accountType: "Group",
    city: "Sharjah",
    area: "Industrial area",
    street: "Shams",
    location: "https://g.page/alshamsmedicalgroup?share",
    hasBranches: true,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 2,
    expand: false,
    branches: [
      {
        branchName: "Al Shams Al Jadeed ",
        branchType: "Clinic",
        branchCity: "Sharjah",
        branchArea: "Industrial Sharjah",
        branchStreet: "Demuscus",
        branchLocation: "https://goo.gl/maps/ZbEn1or58nYKhvSK9",
        _id: "622e2ff2a2c75bcb9aaf641a",
      },
      {
        branchName: "Al Shams Clinic",
        branchType: "Clinic",
        branchCity: "Sharjah",
        branchArea: "Industrial 3",
        branchStreet: "unknown street",
        branchLocation: "https://goo.gl/maps/391Dz4B4EkxASjjm6",
        _id: "622e2ff2a2c75bcb9aaf641b",
      },
    ],
    _id: "622e2ff2a2c75bcb9aaf6419",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Ibn Batuta DrugStore",
    accountType: "Drugstore",
    city: "Sharjah",
    area: "Al Nema",
    street: "Al Nema",
    location: "https://goo.gl/maps/6jka7BaGCguTXTza7",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2ff2a2c75bcb9aaf641c",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Tamimi Drug Store",
    accountType: "Drugstore",
    city: "Sharjah",
    area: "Industrial area",
    street: "Industrial ",
    location: "https://goo.gl/maps/ybWjXf2ZTBCsi5r68",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2ff2a2c75bcb9aaf641d",
  },
  {
    company: "621bb1bda49c57b938fb9b8c",
    country: "6228dac2ad9aef4e064906c3",
    accountName: "Al Zaora Pharmacy",
    accountType: "Pharmacy",
    city: "Ajman",
    area: "Al Swan",
    street: "Ittihad ",
    location: "https://goo.gl/maps/PZr5PqFf28rpdgYJ7",
    hasBranches: false,
    numberOfDoctors: null,
    accountNotes: [],
    numberOfBranches: 0,
    expand: false,
    branches: [],
    _id: "622e2ff2a2c75bcb9aaf641e",
  },

];

export default accountData;

Then in the table if the account hasBranches is true I want to show expanding button to show the branches only onClick

and here is table code

import {
  useTable,
  useGlobalFilter,
  useFilters,
  usePagination,
  useSortBy,
  useRowSelect,
  useExpanded,
} from "react-table";
import ColumnFilter from "./ColumnFilter";
import accountData from "./Data";
import { Columns } from "./Columns";
import { useMemo } from "react";
import "./table.css";
import GlobalFilter from "./GlobalFilter";
import { CheckBox } from "./CheckBos";

const PaginationTable = (props) => {
  const columns = useMemo(() => Columns, []);
  const data = useMemo(() => accountData, []);
  const defaultColumns = useMemo(() => {
    return {
      Filter: ColumnFilter,
    };
  }, []);

  const onClickRow = (e) => {
    const row = e.target;
    console.log(row);
  };

  const tableInstance = useTable(
    {
      columns,
      data,
      defaultColumns,
      expanded: {},
    },
    useFilters,
    useGlobalFilter,
    useSortBy,
    useExpanded,
    usePagination,
    useRowSelect,
    (hooks) => {
      hooks.visibleColumns.push((columns) => [
        // Let's make a column for selection
        {
          id: "selection",
          Header: ({ getToggleAllPageRowsSelectedProps }) => (
            <div>
              <CheckBox {...getToggleAllPageRowsSelectedProps()} />
            </div>
          ),
          Cell: ({ row }) => (
            <div>
              <CheckBox {...row.getToggleRowSelectedProps()} />
            </div>
          ),
        },
        {
          // Build our expander column
          id: "expander", // Make sure it has an ID
          Header: ({ getToggleAllRowsExpandedProps, isAllRowsExpanded }) => (
            <span {...getToggleAllRowsExpandedProps()}>
              {isAllRowsExpanded ? "👇" : "👉"}
            </span>
          ),
          Cell: ({ row, index }) =>
            // Use the row.canExpand and row.getToggleRowExpandedProps prop getter
            // to build the toggle for expanding a row
            row.canExpand
              ? (row.canExpand,
                (
                  <span
                    onClick={() => {
                      console.log(row);
                    }}
                    {...row.getToggleRowExpandedProps({
                      style: {
                        // We can even use the row.depth property
                        // and paddingLeft to indicate the depth
                        // of the row
                        paddingLeft: `${row.depth * 2}rem`,
                      },
                    })}
                  >
                    {row.isExpanded ? "👇" : "👉"}
                  </span>
                ))
              : null,
        },
        ...columns,
      ]);
    }
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    rows,
    getRowId,
    rowsById,
    getSubRows,

    nextPage,
    previousPage,
    canNextPage,
    canPreviousPage,
    pageOptions,
    prepareRow,
    gotoPage,
    pageCount,
    setPageSize,
    canExpand,
    selectedFlatRows,
    allColumns,
    getToggleHideAllColumnsProps,
    state,
    setGlobalFilter,
  } = tableInstance;

  const { globalFilter, pageIndex, pageSize, expanded } = state;

  const expandedRows = useMemo(() => {
    if (accountData?.hasBranches) {
      let arr = [{ 0: false }];
      let d = accountData.hasBranches;
      if (d.getGroupedSamplingStationBySystemId.length > 0) {
        arr = d.getGroupedSamplingStationBySystemId.map((sid, ind) => {
          return { [ind]: true };
        });
      }
      return arr;
    }
  }, []);

  // console.log(canExpand);
  return (
    <>
      <div className="hiding">
        <div className="toggleVisibility">
          <CheckBox {...getToggleHideAllColumnsProps()} /> Toggle All
        </div>
        {allColumns.map((column) => (
          <div key={column.id}>
            <label>
              <input type="checkbox" {...column.getToggleHiddenProps()} />
              {column.Header}
            </label>
          </div>
        ))}
      </div>
      <GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
      <table {...getTableProps()} className="table">
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                  {column.render("Header")}
                  <div>{column.canFilter ? column.render("Filter") : null}</div>
                  <span>
                    {column.isSorted
                      ? column.isSortedDesc
                        ? " 🔽"
                        : " 🔼"
                      : ""}
                  </span>
                </th>
              ))}
            </tr>
          ))}
          <tr></tr>
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map((row, i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
      <pre>
        <code>
          {JSON.stringify(
            { selectedFlatRows: selectedFlatRows.map((row) => row.original) },
            null,
            2
          )}
          ,
        </code>
      </pre>
      <pre>
        <code>{JSON.stringify({ expanded: expanded }, null, 2)}</code>
      </pre>
      <div className="pagination">
        <span className="pages">
          Page{" "}
          <strong>
            {pageIndex + 1} of {pageOptions.length}
          </strong>{" "}
        </span>
        <span className="pages">
          | Go to Page{" "}
          <input
            type="number"
            defaultValue={pageIndex + 1}
            onChange={(e) => {
              const pageNumber = e.target.value
                ? Number(e.target.value) - 1
                : 0;
              gotoPage(pageNumber);
            }}
            className="pageNumber"
            style={{ width: "50px" }}
          />
        </span>
        <select
          value={pageSize}
          onChange={(e) => setPageSize(Number(e.target.value))}
          className="paginationDropDown"
        >
          {[5, 10, 25, 50].map((pageSize) => {
            return (
              <option key={pageSize} value={pageSize}>
                Show {pageSize} per page
              </option>
            );
          })}
        </select>
        <button
          onClick={() => gotoPage(0)}
          disabled={!canPreviousPage}
          className="paginationButton"
        >
          {"<<"}
        </button>
        <button
          onClick={() => previousPage()}
          disabled={!canPreviousPage}
          className="paginationButton"
        >
          Previous
        </button>
        <button
          onClick={() => nextPage()}
          disabled={!canNextPage}
          className="paginationButton"
        >
          Next
        </button>
        <button
          onClick={() => gotoPage(pageCount - 1)}
          disabled={!canNextPage}
          className="paginationButton"
        >
          {">>"}
        </button>
      </div>
    </>
  );
};

export default PaginationTable;

and here is the screen I am getting enter image description here

and here is row log

> allCells: (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] canExpand:
> false cells: (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] depth:
> 0 getRowProps: Æ’ (userProps) getToggleRowExpandedProps: Æ’ (userProps)
> getToggleRowSelectedProps: Æ’ (userProps) id: "12" index: 12
> isExpanded: undefined isSelected: false isSomeSelected: false
> original: {company: '621bb1bda49c57b938fb9b8c', country:
> '6228dac2ad9aef4e064906c3', accountName: 'Prime Medical Center',
> accountType: 'Group', city: 'Dubai', …} originalSubRows: [] subRows:
> [] toggleRowExpanded: Æ’ (set) toggleRowSelected: Æ’ (set) values:
> {accountName: 'Prime Medical Center', accountType: 'Group', city:
> 'Dubai', area: 'Qusais', street: 'Industrial ', …} [[Prototype]]:
> Object

OK, then I am sure it gonna be something very simple to be added what I need to know is

  1. How to detect expanded rows
  2. Where to put the subrows code in the table
  3. How to show them conditionally

I will be grateful if I can get any help soon

Thanks in advance

Upvotes: 0

Views: 26289

Answers (1)

Hatim Fayez
Hatim Fayez

Reputation: 231

For anyone might come here I finally found the solution in this link https://www.freakyjolly.com/react-table-tutorial/ and here also my code

import accountData from "./Data";

export const modifiedData = accountData.map((d) => {
  return {
    accountName: d.accountName,
    accountType: d.accountType,
    city: d.city,
    area: d.area,
    street: d.street,
    location: d.location,
    numberOfBranches: d.numberOfBranches,
    subRows: !d.hasBranches
      ? null
      : d.branches.map((b) => {
          return {
            accountName: b.branchName,
            accountType: b.branchType,
            city: b.branchCity,
            area: b.branchArea,
            street: b.branchStreet,
            location: b.branchLocation,
            numberOfBranches: 0,
          };
        }),
  };
});

Upvotes: 4

Related Questions