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
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
How to detect expanded rows
Where to put the subrows code in the table
How to show them conditionally
I will be grateful if I can get any help soon
Thanks in advance
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,
};
}),
};
});
I tried to set up the functionality to filter my product in an ascending or descending manner.
If you check my code below in order to access the price of each product I tried to map through the products, remove then the dollar sign and sort it to ascending and finally set the new state of the products.
But now I feel confused now because I have the sorted array but no more the entire product when trying to set the new state of the product ??
Thank you for helping
const data = [
{
category: "Sporting Goods",
price: "$49.99",
stocked: true,
name: "Football",
},
{
category: "Sporting Goods",
price: "$9.99",
stocked: true,
name: "Baseball",
},
{
category: "Sporting Goods",
price: "$29.99",
stocked: false,
name: "Basketball",
},
{
category: "Electronics",
price: "$99.99",
stocked: true,
name: "iPod Touch",
},
{
category: "Electronics",
price: "$399.99",
stocked: false,
name: "iPhone 5",
},
{ category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7" },
];
export default data;
const App = () => {
const [searchValue, setSearchValue] = useState("");
const [productsInfo, setProductsInfo] = useState([]);
const handleChange = (e) => {
setSearchValue(e.target.value);
};
const selectedChangeFilter = (e) => {
if (e.target.value === "sporting goods") {
const sportingGoods = data.filter(
(product) => product.category === "Sporting Goods"
);
setProductsInfo(sportingGoods);
}
if (e.target.value === "electronics") {
const electronicsGoods = data.filter(
(product) => product.category === "Electronics"
);
setProductsInfo(electronicsGoods);
}
if (e.target.value === "lowest price") {
const lowestPriceGoods = data
.map((product) => product.price.substr(1))
.sort((a, b) => a - b);
console.log(lowestPriceGoods);
setProductsInfo(lowestPriceGoods);
}
if (e.target.value === "all") {
setProductsInfo(data);
}
};
const searchProducts = (products) => {
if (searchValue.toLowerCase().trim() === "") {
setProductsInfo(products);
} else {
const seekedItem = productsInfo.filter(
(product) =>
product.name.toLowerCase().trim().includes(searchValue) ||
product.category.toLowerCase().trim().includes(searchValue)
);
setProductsInfo(seekedItem);
}
};
return (
<div>
<SearchInput
handleChange={handleChange}
searchValue={searchValue}
selectedChangeFilter={selectedChangeFilter}
/>
<Products
data={data}
searchValue={searchValue}
productsInfo={productsInfo}
searchProducts={searchProducts}
/>
</div>
);
};
export default App;
Try this improved code
const selectedChangeFilter = (e) => {
const { value } = e.target
if (value === "sporting goods") {
const sportingGoods = data.filter(
(product) => product.category === "Sporting Goods"
);
setProductsInfo(sportingGoods);
}
if (value === "electronics") {
const electronicsGoods = data.filter(
(product) => product.category === "Electronics"
);
setProductsInfo(electronicsGoods);
}
if (value === "lowest price") {
const lowestPriceGoods = data.sort((el1,el2) => el1.price.localeCompare(el2.price, undefined, {numeric: true}));
setProductsInfo([...lowestPriceGoods]);
}
if (value === "highest price") {
const highestPriceGoods = data.sort((el1,el2) => el2.price.localeCompare(el1.price, undefined, {numeric: true}));
setProductsInfo([...highestPriceGoods]);
}
if (value === "all") {
setProductsInfo(data);
}
};
You can use string#localeCompare to sort your array based on the number by using numeric property.
const data = [ { category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football", }, { category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball", }, { category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball",}, { category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch", }, { category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5", }, { category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7" }, ];
data.sort((a,b) => a.price.localeCompare(b.price, undefined, {numeric: true}));
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am using MUIDataTable in my React project. I just want to group columns by adding borders to the table. Please find the code below which I am using.
const columns = [
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
[customBodyRender: (value) => {
return (
<div style={{ borderRight: "solid 2px" }}Â >
{value}
</div>
)
}][1]
}
},
{
name: "company",
label: "Company",
options: {
filter: true,
sort: false,
}
},
{
name: "city",
label: "City",
options: {
filter: true,
sort: false,
customBodyRender: (value) => {
return (
<div style={{ borderRight: "solid 2px" }}Â >
{value}
</div>
)
}
}
},
{
name: "state",
label: "State",
options: {
filter: true,
sort: false,
}
},
];
const data = [
{ name: "Joe James", company: "Test Corp", city: "Yonkers", state: "NY" },
{ name: "John Walsh", company: "Test Corp", city: "Hartford", state: "CT" },
{ name: "Bob Herm", company: "Test Corp", city: "Tampa", state: "FL" },
{ name: "James Houston", company: "Test Corp", city: "Dallas", state: "TX" },
{ name: "", company: "", city: "Tampa", state: "" },
{ name: "", company: "", city: "", state: "" },
{ name: "", company: "", city: "Hartford", state: "" },
{ name: "", company: "", city: "", state: "" },
{ name: "", company: "", city: "", state: "" },
{ name: "", company: "", city: "", state: "" },
];
const options = {
filterType: 'checkbox',
};
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
This is not working as expected. Either the border height is not proper or in case of no data in the table row, there is no border at all.
I also want the borders to appear on the table headers.
I have attached the snapshot of the output for reference.
OutputImage
Is there a way to fix this?
there is a PR but it's in beta only https://github.com/gregnb/mui-datatables/pull/1441, not yet merged into the master branch