Repository: gregnb/mui-datatables
Pull request #861 (2019-08-23 23:44:05)

Feature/issue 841 on rows expand
Adds `onRowsExpand` callback that works similarly to `onRowsSelect`.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/25320707/badge)](https://coveralls.io/builds/25320707)

Coverage increased (+1.3%) to 76.519% when pulling **57f6814ae8a078edc5670618852d5e69a7b4ef31 on feature/issue-841-on-rows-expand** into **d1914e4156aea4ff7d6d8ad9794da3ca4b156758 on master**.


Patch:
diff --git a/README.md b/README.md
index a99b7b7..afc102f 100644
--- a/README.md
+++ b/README.md
@@ -174,6 +174,7 @@ The component accepts the following props:
 |**`onDownload`**|function||A callback function that triggers when the user downloads the CSV file. In the callback, you can control what is written to the CSV file. `function(buildHead: (columns) => string, buildBody: (data) => string, columns, data) => string`. Return `false` to cancel download of file.
 |**`viewColumns`**|boolean|true|Show/hide viewColumns icon from toolbar
 |**`onRowsSelect`**|function||Callback function that triggers when row(s) are selected. `function(currentRowsSelected: array, allRowsSelected: array) => void`
+|**`onRowsExpand`**|function||Callback function that triggers when row(s) are expanded. `function(currentRowsExpanded: array, allRowsExpanded: array) => void`
 |**`onRowsDelete`**|function||Callback function that triggers when row(s) are deleted. `function(rowsDeleted: object(lookup: {[dataIndex]: boolean}, data: arrayOfObjects: {index: number, dataIndex: number})) => void OR false` (Returning `false` prevents row deletion.)
 |**`onRowClick`**|function||Callback function that triggers when a row is clicked. `function(rowData: string[], rowMeta: { dataIndex: number, rowIndex: number }) => void`
 |**`onCellClick`**|function||Callback function that triggers when a cell is clicked. `function(colData: any, cellMeta: { colIndex: number, rowIndex: number, dataIndex: number }) => void`
diff --git a/examples/expandable-rows/index.js b/examples/expandable-rows/index.js
index ba67d66..ae742a0 100644
--- a/examples/expandable-rows/index.js
+++ b/examples/expandable-rows/index.js
@@ -92,7 +92,8 @@ class Example extends React.Component {
             </TableCell>
           </TableRow>
         );
-      }
+      },
+      onRowsExpand: (curExpanded, allExpanded) => console.log(curExpanded, allExpanded)
     };
 
     return (
diff --git a/src/MUIDataTable.js b/src/MUIDataTable.js
index d0fe3d5..dde6d9d 100644
--- a/src/MUIDataTable.js
+++ b/src/MUIDataTable.js
@@ -143,6 +143,7 @@ class MUIDataTable extends React.Component {
       customSearchRender: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
       customRowRender: PropTypes.func,
       onRowClick: PropTypes.func,
+      onRowsExpand: PropTypes.func,
       onRowsSelect: PropTypes.func,
       resizableColumns: PropTypes.bool,
       selectableRows: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['none', 'single', 'multiple'])]),
@@ -1021,6 +1022,7 @@ class MUIDataTable extends React.Component {
   toggleExpandRow = row => {
     const { dataIndex } = row;
     let expandedRows = [...this.state.expandedRows.data];
+    let removedRow;
     let rowPos = -1;
 
     for (let cIndex = 0; cIndex < expandedRows.length; cIndex++) {
@@ -1031,13 +1033,14 @@ class MUIDataTable extends React.Component {
     }
 
     if (rowPos >= 0) {
-      expandedRows.splice(rowPos, 1);
+      removedRow = expandedRows.splice(rowPos, 1);
     } else {
       expandedRows.push(row);
     }
 
     this.setState(
       {
+        curExpandedRows: rowPos >= 0 ? removedRow : [row],
         expandedRows: {
           lookup: buildMap(expandedRows),
           data: expandedRows,
@@ -1045,6 +1048,9 @@ class MUIDataTable extends React.Component {
       },
       () => {
         this.setTableAction('expandRow');
+        if (this.options.onRowsExpand) {
+          this.options.onRowsExpand(this.state.curExpandedRows, this.state.expandedRows.data);
+        }
       },
     );
   };


Test patch:
diff --git a/test/MUIDataTable.test.js b/test/MUIDataTable.test.js
index c6265ec..96bb6e2 100644
--- a/test/MUIDataTable.test.js
+++ b/test/MUIDataTable.test.js
@@ -1109,6 +1109,32 @@ describe('<MUIDataTable />', function() {
     assert.deepEqual(JSON.stringify(newDisplayData), expectedResult);
   });
 
+  it('should call onRowsExpand when row is expanded or collapsed', () => {
+    const options = {
+      expandableRows: true,
+      renderExpandableRow: () => <tr><td>foo</td></tr>,
+      expandableRowsOnClick: true,
+      onRowsExpand: spy()
+    };
+    const mountWrapper = mount(<MUIDataTable columns={columns} data={data} options={options} />);
+
+    mountWrapper
+      .find('#MUIDataTableBodyRow-2')
+      .first()
+      .simulate('click');
+
+    assert.strictEqual(options.onRowsExpand.callCount, 1);
+    assert(options.onRowsExpand.calledWith([{ index: 2, dataIndex: 2 }], [{ index: 2, dataIndex: 2 }]));
+
+    mountWrapper
+      .find('#MUIDataTableBodyRow-2')
+      .first()
+      .simulate('click');
+
+    assert.strictEqual(options.onRowsExpand.callCount, 2);
+    assert(options.onRowsExpand.calledWith([{ index: 2, dataIndex: 2 }], []));
+  });
+
   it('should not remove selected data on selectRowDelete when type=cell when onRowsDelete returns false', () => {
     const options = {
       onRowsDelete: () => false,