Repository: gregnb/mui-datatables
Pull request #321 (2018-12-19 02:35:33)

Add ability to override column header
Some background here.  Column header can sort of be overridden by using the customHeadRender option on the column object however if you use this, you lose a lot of out of the box functionality including sorting, adjustable column widths and column hint.  Also, customHeadRender is not applied in the responsive view so if you change the names of the columns, they'll revert when on mobile.

gregnb: More specific, this PR is an attempt to provide the following to each column:
 id, displayName

is that correct?

gregnb: Ok I've left some comments and the project structure overall changed so if you can make those adjustments I'll review again
fantapop: Great. Will do.

On Sat, Jan 5, 2019 at 7:00 AM gregn <notifications@github.com> wrote:

> Ok I've left some comments and the project structure overall changed so if
> you can make those adjustments I'll review again
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/gregnb/mui-datatables/pull/321#issuecomment-451662749>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AGWbqIHRzaz2sG-HyXLtoSa4A5kAElfXks5vAL32gaJpZM4ZZbn->
> .
>

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

Coverage decreased (-0.05%) to 72.49% when pulling **5c4e38b7b929b6bb89cc55b45196c356b299f3de on tracemeinc:master** into **adddef0e6f90b38086aa3937f9c4ccc3dd0718da on gregnb:master**.

fantapop: @gregnb I've made these updates.  Take another look when you have a chance.
gregnb: Looks good @fantapop can you put in some unit tests to confirm that if label is provided that it renders that label and if not provided it uses name? i'll be ready to approve after
fantapop: Yeah. I was looking for an example test which is checking for what is
rendered. Is there one I can model it after?

On Sun, Jan 27, 2019 at 8:46 AM gregn <notifications@github.com> wrote:

> Looks good @fantapop <https://github.com/fantapop> can you put in some
> unit tests to confirm that if label is provided that it renders that label
> and if not provided it uses name? i'll be ready to approve after
>
> —
> You are receiving this because you were mentioned.
>
>
> Reply to this email directly, view it on GitHub
> <https://github.com/gregnb/mui-datatables/pull/321#issuecomment-457933692>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AGWbqNv956mq5hu9MZKlW3iew2jxZNDCks5vHdfVgaJpZM4ZZbn->
> .
>

russell-ingram: Any idea when this will be merged? Was looking for a fix for this exact issue before using mui-datatables to replace some functionality in my existing app.
fantapop: I’ll try to figure out some tests this evening.

On Tue, Jan 29, 2019 at 2:50 PM Russell Ingram <notifications@github.com>
wrote:

> Any idea when this will be merged? Was looking for a fix for this exact
> issue before using mui-datatables to replace some functionality in my
> existing app.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/gregnb/mui-datatables/pull/321#issuecomment-458739188>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AGWbqAzPr1oHUhY4CPK3IuY35QW3ONnbks5vINAngaJpZM4ZZbn->
> .
>

fantapop: @gregnb added some tests here.  Let me know if there's a better way.

Patch:
diff --git a/README.md b/README.md
index a0f5601..30cb87e 100644
--- a/README.md
+++ b/README.md
@@ -193,6 +193,7 @@ const columns = [
 |Name|Type|Description
 |:--:|:-----|:-----|
 |**`Name`**|string|Name of column (This field is required)
+|**`label`**|string|Column Header Name override
 |**`options`**|object|Options for customizing column
 
 
diff --git a/examples/customize-columns/index.js b/examples/customize-columns/index.js
index 016afed..41ddb64 100644
--- a/examples/customize-columns/index.js
+++ b/examples/customize-columns/index.js
@@ -15,6 +15,7 @@ class Example extends React.Component {
         }
       },      
       {
+        label: "Modified Title Label",
         name: "Title",
         options: {
           filter: true,
diff --git a/src/MUIDataTable.js b/src/MUIDataTable.js
index 2cb3513..34845b1 100644
--- a/src/MUIDataTable.js
+++ b/src/MUIDataTable.js
@@ -60,6 +60,7 @@ class MUIDataTable extends React.Component {
       PropTypes.oneOfType([
         PropTypes.string,
         PropTypes.shape({
+          label: PropTypes.string,
           name: PropTypes.string.isRequired,
           options: PropTypes.shape({
             display: PropTypes.string, // enum('true', 'false', 'excluded')
@@ -309,11 +310,12 @@ class MUIDataTable extends React.Component {
 
         columnOptions = {
           name: column.name,
+          label: column.label ? column.label : column.name,
           ...columnOptions,
           ...(column.options ? column.options : {}),
         };
       } else {
-        columnOptions = { ...columnOptions, name: column };
+        columnOptions = { ...columnOptions, name: column, label: column };
       }
 
       columnData.push(columnOptions);
diff --git a/src/components/TableBody.js b/src/components/TableBody.js
index 89b8bd1..b86ff4e 100644
--- a/src/components/TableBody.js
+++ b/src/components/TableBody.js
@@ -107,6 +107,7 @@ class TableBody extends React.Component {
   render() {
     const { classes, columns, toggleExpandRow, options } = this.props;
     const tableRows = this.buildRows();
+    const visibleColCnt = columns.filter(c => c.display !== 'excluded').length;
 
     return (
       <MuiTableBody>
@@ -145,7 +146,7 @@ class TableBody extends React.Component {
                         dataIndex={dataIndex}
                         rowIndex={rowIndex}
                         colIndex={columnIndex}
-                        columnHeader={columns[columnIndex].name}
+                        columnHeader={columns[columnIndex].label}
                         options={options}
                         key={columnIndex}>
                         {column}
@@ -159,7 +160,7 @@ class TableBody extends React.Component {
         ) : (
           <TableBodyRow options={options}>
             <TableBodyCell
-              colSpan={options.selectableRows ? columns.length + 1 : columns.length}
+              colSpan={options.selectableRows ? visibleColCnt + 1 : visibleColCnt}
               options={options}
               colIndex={0}
               rowIndex={0}>
diff --git a/src/components/TableFilter.js b/src/components/TableFilter.js
index 373bbf0..10c1b6c 100644
--- a/src/components/TableFilter.js
+++ b/src/components/TableFilter.js
@@ -155,7 +155,7 @@ class TableFilter extends React.Component {
         <div className={classes.checkboxList} key={index}>
           <FormGroup>
             <Typography variant="body2" className={classes.checkboxListTitle}>
-              {column.name}
+              {column.label}
             </Typography>
             {filterData[index].map((filterColumn, filterIndex) => (
               <FormControlLabel
@@ -196,7 +196,7 @@ class TableFilter extends React.Component {
         {columns.map((column, index) =>
           column.filter ? (
             <FormControl className={classes.selectFormControl} key={index}>
-              <InputLabel htmlFor={column.name}>{column.name}</InputLabel>
+              <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
               <Select
                 value={filterList[index].toString() || textLabels.all}
                 name={column.name}
@@ -250,7 +250,7 @@ class TableFilter extends React.Component {
         {columns.map((column, index) =>
           column.filter ? (
             <FormControl className={classes.selectFormControl} key={index}>
-              <InputLabel htmlFor={column.name}>{column.name}</InputLabel>
+              <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
               <Select
                 multiple
                 value={filterList[index] || []}
diff --git a/src/components/TableHead.js b/src/components/TableHead.js
index 5e7ead1..7f430a0 100644
--- a/src/components/TableHead.js
+++ b/src/components/TableHead.js
@@ -67,7 +67,7 @@ class TableHead extends React.Component {
                   toggleSort={this.handleToggleColumn}
                   hint={column.hint}
                   options={options}>
-                  {column.name}
+                  {column.label}
                 </TableHeadCell>
               )),
           )}
diff --git a/src/components/TableViewCol.js b/src/components/TableViewCol.js
index 9850bff..a6c08c2 100644
--- a/src/components/TableViewCol.js
+++ b/src/components/TableViewCol.js
@@ -89,7 +89,7 @@ class TableViewCol extends React.Component {
                       value={column.name}
                     />
                   }
-                  label={column.name}
+                  label={column.label}
                 />
               )
             );


Test patch:
diff --git a/test/MUIDataTable.test.js b/test/MUIDataTable.test.js
index 53b0d32..94ec229 100644
--- a/test/MUIDataTable.test.js
+++ b/test/MUIDataTable.test.js
@@ -24,7 +24,7 @@ describe('<MUIDataTable />', function() {
     columns = [
       { name: 'Name', options: { customBodyRender: renderName } },
       'Company',
-      { name: 'City', options: { customBodyRender: renderCities } },
+      { name: 'City', label: 'City Label', options: { customBodyRender: renderCities } },
       { name: 'State' },
     ];
     data = [
@@ -83,6 +83,7 @@ describe('<MUIDataTable />', function() {
         name: 'Name',
         sort: true,
         filter: true,
+        label: 'Name',
         download: true,
         sortDirection: null,
         viewColumns: true,
@@ -93,6 +94,7 @@ describe('<MUIDataTable />', function() {
         name: 'Company',
         sort: true,
         filter: true,
+        label: 'Company',
         download: true,
         viewColumns: true,
         sortDirection: null,
@@ -102,6 +104,7 @@ describe('<MUIDataTable />', function() {
         name: 'City',
         sort: true,
         filter: true,
+        label: 'City Label',
         download: true,
         viewColumns: true,
         sortDirection: null,
@@ -112,6 +115,7 @@ describe('<MUIDataTable />', function() {
         name: 'State',
         sort: true,
         filter: true,
+        label: 'State',
         download: true,
         viewColumns: true,
         sortDirection: null,
@@ -360,6 +364,7 @@ describe('<MUIDataTable />', function() {
         display: 'false',
         sort: true,
         filter: true,
+        label: 'Name',
         download: true,
         sortDirection: null,
         customBodyRender: renderName,
@@ -370,6 +375,7 @@ describe('<MUIDataTable />', function() {
         display: 'true',
         sort: true,
         filter: true,
+        label: 'Company',
         download: true,
         viewColumns: true,
         sortDirection: null,
@@ -379,6 +385,7 @@ describe('<MUIDataTable />', function() {
         display: 'true',
         sort: true,
         filter: true,
+        label: 'City Label',
         download: true,
         sortDirection: null,
         customBodyRender: renderCities,
@@ -389,6 +396,7 @@ describe('<MUIDataTable />', function() {
         display: 'true',
         sort: true,
         filter: true,
+        label: 'State',
         download: true,
         viewColumns: true,
         sortDirection: null,
diff --git a/test/MUIDataTableFilter.test.js b/test/MUIDataTableFilter.test.js
index b99df51..057c588 100644
--- a/test/MUIDataTableFilter.test.js
+++ b/test/MUIDataTableFilter.test.js
@@ -7,6 +7,7 @@ import Select from '@material-ui/core/Select';
 import Checkbox from '@material-ui/core/Checkbox';
 import TextField from '@material-ui/core/TextField';
 import TableFilter from '../src/components/TableFilter';
+import Typography from '@material-ui/core/Typography';
 
 describe('<TableFilter />', function() {
   let data;
@@ -15,10 +16,10 @@ describe('<TableFilter />', function() {
 
   beforeEach(() => {
     columns = [
-      { name: 'First Name', display: true, sort: true, filter: true, sortDirection: 'desc' },
-      { name: 'Company', display: true, sort: true, filter: true, sortDirection: 'desc' },
-      { name: 'City', display: true, sort: true, filter: true, sortDirection: 'desc' },
-      { name: 'State', display: true, sort: true, filter: true, sortDirection: 'desc' },
+      { name: 'First Name', label: 'First Name', display: true, sort: true, filter: true, sortDirection: 'desc' },
+      { name: 'Company', label: 'Company', display: true, sort: true, filter: true, sortDirection: 'desc' },
+      { name: 'City', label: 'City Label', display: true, sort: true, filter: true, sortDirection: 'desc' },
+      { name: 'State', label: 'State', display: true, sort: true, filter: true, sortDirection: 'desc' },
     ];
 
     data = [
@@ -36,6 +37,19 @@ describe('<TableFilter />', function() {
     ];
   });
 
+  it('should render label as filter name', () => {
+    const options = { filterType: 'checkbox', textLabels };
+    const filterList = [[], [], [], []];
+    const shallowWrapper = mount(
+      <TableFilter columns={columns} filterData={filterData} filterList={filterList} options={options} />,
+    );
+    const labels = shallowWrapper
+      .find(Typography)
+      .filterWhere(n => n.html().match(/MUIDataTableFilter-checkboxListTitle/))
+      .map(n => n.text());
+    assert.deepEqual(labels, ['First Name', 'Company', 'City Label', 'State']);
+  });
+
   it("should data table filter view with checkboxes if filterType = 'checkbox'", () => {
     const options = { filterType: 'checkbox', textLabels };
     const filterList = [[], [], [], []];
diff --git a/test/MUIDataTableHead.test.js b/test/MUIDataTableHead.test.js
index 8b227c7..888d098 100644
--- a/test/MUIDataTableHead.test.js
+++ b/test/MUIDataTableHead.test.js
@@ -12,10 +12,10 @@ describe('<TableHead />', function() {
 
   before(() => {
     columns = [
-      { name: 'First Name', display: 'true', sort: null },
-      { name: 'Company', display: 'true', sort: null },
-      { name: 'City', display: 'true', sort: null },
-      { name: 'State', display: 'true', sort: null },
+      { name: 'First Name', label: 'First Name', display: 'true', sort: null },
+      { name: 'Company', label: 'Company', display: 'true', sort: null },
+      { name: 'City', label: 'City Label', display: 'true', sort: null },
+      { name: 'State', label: 'State', display: 'true', sort: null },
     ];
 
     handleHeadUpdateRef = () => {};
@@ -38,6 +38,23 @@ describe('<TableHead />', function() {
     assert.strictEqual(actualResult.length, 4);
   });
 
+  it('should render the label in the table head cell', () => {
+    const options = {};
+    const toggleSort = () => {};
+
+    const mountWrapper = mount(
+      <TableHead
+        columns={columns}
+        options={options}
+        setCellRef={() => {}}
+        handleHeadUpdateRef={handleHeadUpdateRef}
+        toggleSort={toggleSort}
+      />,
+    );
+    const labels = mountWrapper.find(TableHeadCell).map(n => n.text());
+    assert.deepEqual(labels, ['First Name', 'Company', 'City Label', 'State']);
+  });
+
   it('should render a table head with no cells', () => {
     const options = {};
     const toggleSort = () => {};
diff --git a/test/MUIDataTableViewCol.test.js b/test/MUIDataTableViewCol.test.js
index e52ffa0..8eaf50d 100644
--- a/test/MUIDataTableViewCol.test.js
+++ b/test/MUIDataTableViewCol.test.js
@@ -5,13 +5,19 @@ import { assert, expect, should } from 'chai';
 import Checkbox from '@material-ui/core/Checkbox';
 import TableViewCol from '../src/components/TableViewCol';
 import textLabels from '../src/textLabels';
+import { FormControlLabel } from '@material-ui/core';
 
 describe('<TableViewCol />', function() {
   let columns;
   let options;
 
   before(() => {
-    columns = ['a', 'b', 'c', 'd'];
+    columns = [
+      { name: 'a', label: 'A' },
+      { name: 'b', label: 'B' },
+      { name: 'c', label: 'C' },
+      { name: 'd', label: 'D' },
+    ];
     options = {
       textLabels,
     };
@@ -24,6 +30,12 @@ describe('<TableViewCol />', function() {
     assert.strictEqual(actualResult.length, 4);
   });
 
+  it('should labels as view column names when present', () => {
+    const mountWrapper = mount(<TableViewCol columns={columns} options={options} />);
+    const labels = mountWrapper.find(FormControlLabel).map(n => n.text());
+    assert.deepEqual(labels, ['A', 'B', 'C', 'D']);
+  });
+
   it('should trigger onColumnUpdate prop callback when calling method handleColChange', () => {
     const onColumnUpdate = spy();