Skip to content

Commit

Permalink
[DataGrid] Add indexes relative to the filtered rows and the current …
Browse files Browse the repository at this point in the history
…page to the `getRowClassName` and `getRowSpacing` props (mui#3882)
  • Loading branch information
flaviendelangle authored and alexfauquette committed Aug 26, 2022
1 parent 753275b commit d9f2c13
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 20 deletions.
58 changes: 58 additions & 0 deletions docs/data/data-grid/style/StripedGrid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import { alpha, styled } from '@mui/material/styles';
import { DataGrid, gridClasses } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const ODD_OPACITY = 0.2;

const StripedDataGrid = styled(DataGrid)(({ theme }) => ({
[`& .${gridClasses.row}.even`]: {
backgroundColor: theme.palette.grey[200],
'&:hover, &.Mui-hovered': {
backgroundColor: alpha(theme.palette.primary.main, ODD_OPACITY),
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
'&.Mui-selected': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY + theme.palette.action.selectedOpacity,
),
'&:hover, &.Mui-hovered': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY +
theme.palette.action.selectedOpacity +
theme.palette.action.hoverOpacity,
),
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY + theme.palette.action.selectedOpacity,
),
},
},
},
},
}));

export default function StripedGrid() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 200,
});

return (
<div style={{ height: 400, width: '100%' }}>
<StripedDataGrid
loading={loading}
{...data}
getRowClassName={(params) =>
params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
/>
</div>
);
}
58 changes: 58 additions & 0 deletions docs/data/data-grid/style/StripedGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import { alpha, styled } from '@mui/material/styles';
import { DataGrid, gridClasses } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const ODD_OPACITY = 0.2;

const StripedDataGrid = styled(DataGrid)(({ theme }) => ({
[`& .${gridClasses.row}.even`]: {
backgroundColor: theme.palette.grey[200],
'&:hover, &.Mui-hovered': {
backgroundColor: alpha(theme.palette.primary.main, ODD_OPACITY),
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
'&.Mui-selected': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY + theme.palette.action.selectedOpacity,
),
'&:hover, &.Mui-hovered': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY +
theme.palette.action.selectedOpacity +
theme.palette.action.hoverOpacity,
),
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: alpha(
theme.palette.primary.main,
ODD_OPACITY + theme.palette.action.selectedOpacity,
),
},
},
},
},
}));

export default function StripedGrid() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 200,
});

return (
<div style={{ height: 400, width: '100%' }}>
<StripedDataGrid
loading={loading}
{...data}
getRowClassName={(params) =>
params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
/>
</div>
);
}
7 changes: 7 additions & 0 deletions docs/data/data-grid/style/StripedGrid.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<StripedDataGrid
loading={loading}
{...data}
getRowClassName={(params) =>
params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
/>
10 changes: 9 additions & 1 deletion docs/data/data-grid/style/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,17 @@ Choose between one of the following values: 'left' | 'right' | 'center'.

**Note**: You must use `headerAlign` to align the content of the header.

## Striped rows

The following demo illustrates how the rows of the grid can be stripped.

{{"demo": "StripedGrid.js", "bg": "inline"}}

## Custom theme

The following demo leverages the CSS customization API to match the Ant Design specification.
You can use the `indexRelativeToCurrentPage` param passed to `getRowClassName` to apply alternating styles to the rows.

The following demo illustrates how this can be achieved.

{{"demo": "AntDesignGrid.js", "defaultCodeOpen": false}}

Expand Down
17 changes: 9 additions & 8 deletions docs/pages/x/api/data-grid/grid-row-class-name-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import { GridRowClassNameParams } from '@mui/x-data-grid';

## Properties

| Name | Type | Description |
| :-------------------------------------------- | :---------------------------------------------------------------------- | :--------------------------------------------------------- |
| <span class="prop-name">columns</span> | <span class="prop-type">GridColumns</span> | All grid columns. |
| <span class="prop-name">getValue</span> | <span class="prop-type">(id: GridRowId, field: string) =&gt; any</span> | Get the cell value of a row and field. |
| <span class="prop-name">id</span> | <span class="prop-type">GridRowId</span> | The grid row id. |
| <span class="prop-name">isFirstVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the first visible or not. |
| <span class="prop-name">isLastVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the last visible or not. |
| <span class="prop-name">row</span> | <span class="prop-type">R</span> | The row model of the row that the current cell belongs to. |
| Name | Type | Description |
| :-------------------------------------------------------- | :---------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |
| <span class="prop-name">columns</span> | <span class="prop-type">GridColumns</span> | All grid columns. |
| <span class="prop-name">getValue</span> | <span class="prop-type">(id: GridRowId, field: string) =&gt; any</span> | Get the cell value of a row and field. |
| <span class="prop-name">id</span> | <span class="prop-type">GridRowId</span> | The grid row id. |
| <span class="prop-name">indexRelativeToCurrentPage</span> | <span class="prop-type">number</span> | Index of the row in the current page.<br />If the pagination is disabled, it will be the index relative to all filtered rows. |
| <span class="prop-name">isFirstVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the first visible or not. |
| <span class="prop-name">isLastVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the last visible or not. |
| <span class="prop-name">row</span> | <span class="prop-type">R</span> | The row model of the row that the current cell belongs to. |
13 changes: 7 additions & 6 deletions docs/pages/x/api/data-grid/grid-row-spacing-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import { GridRowSpacingParams } from '@mui/x-data-grid';

## Properties

| Name | Type | Description |
| :-------------------------------------------- | :--------------------------------------- | :-------------------------------------------- |
| <span class="prop-name">id</span> | <span class="prop-type">GridRowId</span> | The row id. |
| <span class="prop-name">isFirstVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the first visible or not. |
| <span class="prop-name">isLastVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the last visible or not. |
| <span class="prop-name">model</span> | <span class="prop-type">R</span> | The row model. |
| Name | Type | Description |
| :-------------------------------------------------------- | :--------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |
| <span class="prop-name">id</span> | <span class="prop-type">GridRowId</span> | The row id. |
| <span class="prop-name">indexRelativeToCurrentPage</span> | <span class="prop-type">number</span> | Index of the row in the current page.<br />If the pagination is disabled, it will be the index relative to all filtered rows. |
| <span class="prop-name">isFirstVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the first visible or not. |
| <span class="prop-name">isLastVisible</span> | <span class="prop-type">boolean</span> | Whether this row is the last visible or not. |
| <span class="prop-name">model</span> | <span class="prop-type">R</span> | The row model. |
17 changes: 16 additions & 1 deletion packages/grid/x-data-grid/src/components/GridRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ import { useGridVisibleRows } from '../hooks/utils/useGridVisibleRows';
import { findParentElementFromClassName } from '../utils/domUtils';
import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../colDef/gridCheckboxSelectionColDef';
import { GRID_ACTIONS_COLUMN_TYPE } from '../colDef/gridActionsColDef';
import { GridRenderEditCellParams } from '../models/params/gridCellParams';

export interface GridRowProps {
rowId: GridRowId;
selected: boolean;
/**
* Index of the row in the whole sorted and filtered dataset.
* If some rows above have expanded children, this index also take those children into account.
*/
index: number;
rowHeight: number;
containerWidth: number;
Expand Down Expand Up @@ -214,6 +219,7 @@ function GridRow(props: React.HTMLAttributes<HTMLDivElement> & GridRowProps) {
...apiRef.current.getRowParams(rowId),
isFirstVisible: indexRelativeToCurrentPage === 0,
isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1,
indexRelativeToCurrentPage,
};

rowClassName = rootProps.getRowClassName(rowParams);
Expand Down Expand Up @@ -257,7 +263,12 @@ function GridRow(props: React.HTMLAttributes<HTMLDivElement> & GridRowProps) {
}

if (editCellState != null && column.renderEditCell) {
const params = { ...cellParams, ...editCellState, api: apiRef.current };
const params: GridRenderEditCellParams = {
...cellParams,
...editCellState,
api: apiRef.current,
};

content = column.renderEditCell(params);
// TODO move to GridCell
classNames.push(clsx(gridClasses['cell--editing'], rootProps.classes?.['cell--editing']));
Expand Down Expand Up @@ -336,6 +347,10 @@ GridRow.propTypes = {
containerWidth: PropTypes.number.isRequired,
editRowsState: PropTypes.object.isRequired,
firstColumnToRender: PropTypes.number.isRequired,
/**
* Index of the row in the whole sorted and filtered dataset.
* If some rows above have expanded children, this index also take those children into account.
*/
index: PropTypes.number.isRequired,
isLastVisible: PropTypes.bool,
lastColumnToRender: PropTypes.number.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ export const useGridRowsMeta = (
const initialHeights: Record<string, number> = { base: baseRowHeight };

if (getRowSpacing) {
const index = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(
row.id,
);

const spacing = getRowSpacing({
...row,
isFirstVisible: index === 0,
isLastVisible: index === currentPage.rows.length - 1,
isFirstVisible: indexRelativeToCurrentPage === 0,
isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1,
indexRelativeToCurrentPage,
});

initialHeights.spacingTop = spacing.top ?? 0;
Expand Down
5 changes: 5 additions & 0 deletions packages/grid/x-data-grid/src/models/params/gridRowParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ interface GridRowVisibilityParams {
* Whether this row is the last visible or not.
*/
isLastVisible: boolean;
/**
* Index of the row in the current page.
* If the pagination is disabled, it will be the index relative to all filtered rows.
*/
indexRelativeToCurrentPage: number;
}

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/grid/x-data-grid/src/tests/rows.DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,16 +374,17 @@ describe('<DataGrid /> - Rows', () => {
it('should be called with the correct params', () => {
const getRowSpacing = stub().returns({});
render(<TestCase getRowSpacing={getRowSpacing} pageSize={2} rowsPerPageOptions={[2]} />);

expect(getRowSpacing.args[0][0]).to.deep.equal({
isFirstVisible: true,
isLastVisible: false,
indexRelativeToCurrentPage: 0,
id: 0,
model: rows[0],
});
expect(getRowSpacing.args[1][0]).to.deep.equal({
isFirstVisible: false,
isLastVisible: true,
indexRelativeToCurrentPage: 1,
id: 1,
model: rows[1],
});
Expand All @@ -394,12 +395,14 @@ describe('<DataGrid /> - Rows', () => {
expect(getRowSpacing.args[0][0]).to.deep.equal({
isFirstVisible: true,
isLastVisible: false,
indexRelativeToCurrentPage: 0,
id: 2,
model: rows[2],
});
expect(getRowSpacing.args[1][0]).to.deep.equal({
isFirstVisible: false,
isLastVisible: true,
indexRelativeToCurrentPage: 1,
id: 3,
model: rows[3],
});
Expand Down

0 comments on commit d9f2c13

Please sign in to comment.