diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js
new file mode 100644
index 0000000000000..837ea2546b6bb
--- /dev/null
+++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js
@@ -0,0 +1,55 @@
+import * as React from 'react';
+import {
+ DataGridPremium,
+ useGridApiRef,
+ useGridSelector,
+ useKeepGroupedColumnsHidden,
+ useGridApiContext,
+ gridFilteredDescendantRowCountSelector,
+} from '@mui/x-data-grid-premium';
+import { useMovieData } from '@mui/x-data-grid-generator';
+import { Box } from '@mui/material';
+
+function CustomFooterRowCount(props) {
+ const { visibleRowCount: topLevelRowCount } = props;
+ const apiRef = useGridApiContext();
+ const descendantRowCount = useGridSelector(
+ apiRef,
+ gridFilteredDescendantRowCountSelector,
+ );
+
+ return (
+
+ {descendantRowCount} row{descendantRowCount > 1 ? 's' : ''} in{' '}
+ {topLevelRowCount} group
+ {topLevelRowCount > 1 ? 's' : ''}
+
+ );
+}
+
+export default function RowGroupingChildRowCount() {
+ const data = useMovieData();
+ const apiRef = useGridApiRef();
+
+ const initialState = useKeepGroupedColumnsHidden({
+ apiRef,
+ initialState: {
+ rowGrouping: {
+ model: ['company'],
+ },
+ },
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx
new file mode 100644
index 0000000000000..514aa8358b3cc
--- /dev/null
+++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx
@@ -0,0 +1,56 @@
+import * as React from 'react';
+import {
+ DataGridPremium,
+ GridRowCountProps,
+ useGridApiRef,
+ useGridSelector,
+ useKeepGroupedColumnsHidden,
+ useGridApiContext,
+ gridFilteredDescendantRowCountSelector,
+} from '@mui/x-data-grid-premium';
+import { useMovieData } from '@mui/x-data-grid-generator';
+import { Box } from '@mui/material';
+
+function CustomFooterRowCount(props: GridRowCountProps) {
+ const { visibleRowCount: topLevelRowCount } = props;
+ const apiRef = useGridApiContext();
+ const descendantRowCount = useGridSelector(
+ apiRef,
+ gridFilteredDescendantRowCountSelector,
+ );
+
+ return (
+
+ {descendantRowCount} row{descendantRowCount > 1 ? 's' : ''} in{' '}
+ {topLevelRowCount} group
+ {topLevelRowCount > 1 ? 's' : ''}
+
+ );
+}
+
+export default function RowGroupingChildRowCount() {
+ const data = useMovieData();
+ const apiRef = useGridApiRef();
+
+ const initialState = useKeepGroupedColumnsHidden({
+ apiRef,
+ initialState: {
+ rowGrouping: {
+ model: ['company'],
+ },
+ },
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview
new file mode 100644
index 0000000000000..f9d69b63cb0ae
--- /dev/null
+++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md b/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md
index 014bbd94411a6..90067a6eb2715 100644
--- a/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md
+++ b/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md
@@ -25,3 +25,11 @@ By default, the row grouping column uses `sortComparator` of the grouping column
To sort the row groups by the number of child rows, you can override it using `groupingColDef.sortComparator`:
{{"demo": "RowGroupingSortByChildRows.js", "bg": "inline", "defaultCodeOpen": false}}
+
+## Dispaying child row count in footer
+
+By default, the row count in the footer is the number of top level rows that are visible after filtering.
+
+In the demo below, a `CustomFooterRowCount` component is added to the `footerRowCount` slot. This component uses the `gridFilteredDescendantRowCountSelector` to get the number of child rows and display it alongside the number of groups.
+
+{{"demo": "RowGroupingChildRowCount.js", "bg": "inline", "defaultCodeOpen": false}}
diff --git a/docs/pages/x/api/data-grid/selectors.json b/docs/pages/x/api/data-grid/selectors.json
index 10cb5c8c44395..ad0e4aefd23db 100644
--- a/docs/pages/x/api/data-grid/selectors.json
+++ b/docs/pages/x/api/data-grid/selectors.json
@@ -194,6 +194,20 @@
"description": "Get the filterable columns as a lookup (an object containing the field for keys and the definition for values).",
"supportsApiRef": true
},
+ {
+ "name": "gridFilteredDescendantRowCountSelector",
+ "returnType": "number",
+ "category": "Filtering",
+ "description": "Get the amount of descendant rows accessible after the filtering process.",
+ "supportsApiRef": true
+ },
+ {
+ "name": "gridFilteredRowCountSelector",
+ "returnType": "number",
+ "category": "Filtering",
+ "description": "Get the amount of rows accessible after the filtering process.\nIncludes top level and descendant rows.",
+ "supportsApiRef": true
+ },
{
"name": "gridFilteredSortedRowEntriesSelector",
"returnType": "GridRowEntry[]",
diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts
index 40fa6d9c6a3bd..9d376a2321f23 100644
--- a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts
+++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts
@@ -131,6 +131,26 @@ export const gridFilteredTopLevelRowCountSelector = createSelector(
(visibleSortedTopLevelRows) => visibleSortedTopLevelRows.length,
);
+/**
+ * Get the amount of rows accessible after the filtering process.
+ * Includes top level and descendant rows.
+ * @category Filtering
+ */
+export const gridFilteredRowCountSelector = createSelector(
+ gridFilteredSortedRowEntriesSelector,
+ (filteredSortedRowEntries) => filteredSortedRowEntries.length,
+);
+
+/**
+ * Get the amount of descendant rows accessible after the filtering process.
+ * @category Filtering
+ */
+export const gridFilteredDescendantRowCountSelector = createSelector(
+ gridFilteredRowCountSelector,
+ gridFilteredTopLevelRowCountSelector,
+ (totalRowCount, topLevelRowCount) => totalRowCount - topLevelRowCount,
+);
+
/**
* @category Filtering
* @ignore - do not document.
diff --git a/scripts/x-data-grid-premium.exports.json b/scripts/x-data-grid-premium.exports.json
index 12f86b8d61963..6ef4a77490067 100644
--- a/scripts/x-data-grid-premium.exports.json
+++ b/scripts/x-data-grid-premium.exports.json
@@ -324,6 +324,8 @@
{ "name": "GridFilterAltIcon", "kind": "Variable" },
{ "name": "GridFilterApi", "kind": "Interface" },
{ "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" },
+ { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" },
+ { "name": "gridFilteredRowCountSelector", "kind": "Variable" },
{ "name": "gridFilteredRowsLookupSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" },
diff --git a/scripts/x-data-grid-pro.exports.json b/scripts/x-data-grid-pro.exports.json
index 22f8ca72e6d0d..8d972b055ecc6 100644
--- a/scripts/x-data-grid-pro.exports.json
+++ b/scripts/x-data-grid-pro.exports.json
@@ -293,6 +293,8 @@
{ "name": "GridFilterAltIcon", "kind": "Variable" },
{ "name": "GridFilterApi", "kind": "Interface" },
{ "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" },
+ { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" },
+ { "name": "gridFilteredRowCountSelector", "kind": "Variable" },
{ "name": "gridFilteredRowsLookupSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" },
diff --git a/scripts/x-data-grid.exports.json b/scripts/x-data-grid.exports.json
index ec3c2edb53e86..3d911f1ed3776 100644
--- a/scripts/x-data-grid.exports.json
+++ b/scripts/x-data-grid.exports.json
@@ -263,6 +263,8 @@
{ "name": "GridFilterAltIcon", "kind": "Variable" },
{ "name": "GridFilterApi", "kind": "Interface" },
{ "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" },
+ { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" },
+ { "name": "gridFilteredRowCountSelector", "kind": "Variable" },
{ "name": "gridFilteredRowsLookupSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" },
{ "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" },