Skip to content

Commit

Permalink
✨(react) make optional DataGrid row selection
Browse files Browse the repository at this point in the history
When using the selection feature on another project we realized that
we needed to make some row non selectable at all by hiding the checkbox
completely.
  • Loading branch information
NathanVss committed Aug 21, 2024
1 parent 418fac1 commit e2adb7d
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/wise-coins-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": minor
---

make optional DataGrid row selection
65 changes: 64 additions & 1 deletion packages/react/src/components/DataGrid/SimpleDataGrid.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen, waitFor } from "@testing-library/react";
import { queryByRole, render, screen, waitFor } from "@testing-library/react";
import React, { useState } from "react";
import { faker } from "@faker-js/faker";
import { getAllByRole, getByRole, within } from "@testing-library/dom";
Expand Down Expand Up @@ -267,6 +267,69 @@ describe("<SimpleDataGrid/>", () => {
expect(lastRowSelection[rowsToSelect[1].id]).toBe(true);
});
});
it.only("should not render selection checkboxes for unselectable rows", async () => {
const rows = Array.from(Array(2))
.map(() => ({
id: faker.string.uuid(),
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
email: faker.internet.email(),
address: faker.location.streetAddress(),
}))
.sort((a, b) => a.firstName.localeCompare(b.firstName));
rows[0].email = "[email protected]";

const Wrapper = () => {
const [rowSelection, setRowSelection] = useState({});
lastRowSelection = rowSelection;
return (
<CunninghamProvider>
<SimpleDataGrid
columns={[
{
field: "firstName",
headerName: "First name",
},
{
field: "lastName",
headerName: "Last name",
},
{
field: "email",
headerName: "Email",
},
{
field: "address",
headerName: "Address",
},
]}
rows={rows}
defaultSortModel={[
{
field: "firstName",
sort: "asc",
},
]}
enableRowSelection={(row) =>
row.original.email !== "[email protected]"
}
rowSelection={rowSelection}
onRowSelectionChange={setRowSelection}
/>
</CunninghamProvider>
);
};

render(<Wrapper />);

// Check first row.
let element = screen.getByTestId(rows[0].id);
expect(queryByRole(element, "checkbox")).not.toBeInTheDocument();

// Check second row.
element = screen.getByTestId(rows[1].id);
expect(getByRole(element, "checkbox")).toBeInTheDocument();
});
it("should render a grid with working sortable columns", async () => {
const rows = Array.from(Array(23))
.map(() => ({
Expand Down
4 changes: 4 additions & 0 deletions packages/react/src/components/DataGrid/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ below the table.

<Canvas sourceState="shown" of={Stories.ClientSideWithPagination}/>

You can also make a row non selectable by setting using `enableRowSelection` as a callback function that returns a boolean based on a condition.

<Canvas sourceState="shown" of={Stories.RowSelectionOptional}/>

As you can see, with `SimpleDataGrid` you can easily add pagination, sorting without have to worry about controlling
their states.

Expand Down
41 changes: 41 additions & 0 deletions packages/react/src/components/DataGrid/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,47 @@ export const ClientSideWithPagination = () => {
);
};

export const RowSelectionOptional = () => {
const [rowSelection, setRowSelection] = useState({});

return (
<>
<SimpleDataGrid
columns={[
{
field: "carName",
headerName: "Car name",
enableSorting: false,
},
{
field: "year",
headerName: "Year",
},
{
field: "price",
headerName: "Price ($)",
highlight: true,
},
]}
rows={databaseCars}
defaultPaginationParams={{
pageSize: 5,
}}
defaultSortModel={[
{
field: "price",
sort: "desc",
},
]}
enableRowSelection={(row) => row.original.year < 2024}
rowSelection={rowSelection}
onRowSelectionChange={setRowSelection}
/>
<div>Selected rows: {Object.keys(rowSelection).join(", ")}</div>
</>
);
};

export const FullServerSide = () => {
const database = useMemo(() => [...databaseUsersServer], []);
const [rowSelection, setRowSelection] = useState({});
Expand Down
23 changes: 14 additions & 9 deletions packages/react/src/components/DataGrid/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,20 @@ export const useHeadlessColumns = <T extends Row>({
id: HEADER_ID_SELECT,
size: 34,
header: () => null,
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
disabled={!row.getCanSelect}
indeterminate={row.getIsSomeSelected()}
onChange={row.getToggleSelectedHandler()}
aria-label={t("components.datagrid.row_selection_aria")}
/>
),
cell: ({ row }) => {
if (!row.getCanSelect()) {
return null;
}
return (
<Checkbox
checked={row.getIsSelected()}
disabled={!row.getCanSelect}
indeterminate={row.getIsSomeSelected()}
onChange={row.getToggleSelectedHandler()}
aria-label={t("components.datagrid.row_selection_aria")}
/>
);
},
}),
...headlessColumns,
];
Expand Down

0 comments on commit e2adb7d

Please sign in to comment.