react-bootstrap-table2 icon indicating copy to clipboard operation
react-bootstrap-table2 copied to clipboard

Multiple Header Rows support?

Open bookworm2death opened this issue 7 years ago • 29 comments

Hi @AllenFang I'm a big fan of your react-bootstrap-table(s). My current project is using your original react-bootstrap-table, but i'm trying to migrate to your react-bootstrap-table-next because my customer wants that autoSelectText option. But my current table has 2 header rows, the first spanning multiple columns. And it looks like the new table structure doesn't handle that since datafield is required, and the column definition is missing the row & colspan attributes. Is there any plans to migrate this functionality or do you know of a way to insert an extra header? image

Thank you!

bookworm2death avatar Oct 17 '18 20:10 bookworm2death

@bookworm2death firstly, say thanks to you.

Currently, I dont have plan to support the header colspan or rowspan. However, I will try to implement it ASAP. Sorry I can not tell you when I can support it. It's depends on my time. thanks!

AllenFang avatar Oct 21 '18 07:10 AllenFang

Hi @bookworm2death, were you ever able to get this to work? I see they have an example on the React Bootstrap Table home page, but I must be missing how to do this in the docs. react-bootstrap-table2-sample

benkotch avatar Apr 25 '19 04:04 benkotch

@bookworm2death any luck with this?

arhimmel avatar May 19 '19 21:05 arhimmel

@arhimmel It looks like they removed that feature in the current versions. I ended up going with a different solution.

benkotch avatar May 19 '19 21:05 benkotch

any news about multi header?

Fornori avatar Sep 28 '19 08:09 Fornori

Can we revisit this? I was excited when I saw the image on the homepage, but disappointed that it is not a feature.

tcboles avatar Oct 30 '19 11:10 tcboles

Hi @AllenFang, Were you able to put this feature on the roadmap? The example image on the homepage looks promising, but I cannot find an implemented example of the multiple header rows.

dstruyve avatar Feb 26 '20 10:02 dstruyve

Any update?

thedmeyer avatar Apr 18 '20 01:04 thedmeyer

Any update?

Ended using http://allenfang.github.io/react-bootstrap-table/example.html , that supports header groups

amcm23 avatar Apr 20 '20 13:04 amcm23

Hi team

Any update on this?

Ksenia0479 avatar Jul 09 '20 06:07 Ksenia0479

I also would like to know 👍

Mikeez avatar Sep 01 '20 15:09 Mikeez

Any update?

josearaujo avatar Dec 08 '20 17:12 josearaujo

Any update?

sashasemeniuk avatar Mar 01 '21 12:03 sashasemeniuk

Any news on this? This seems like a really important function and I'm surprised it's not included yet.

dennysemko avatar Sep 13 '21 15:09 dennysemko

hi, any update?

skg-thienpg avatar Feb 22 '22 10:02 skg-thienpg

At least give us a way of hooking into the header so we can implement ourselves. There's no work around to this and something completely normal for HTML tables. It's been 4 years.

duhmojo avatar Feb 22 '22 23:02 duhmojo

Any update on this ? @AllenFang

arjunsoota avatar Sep 26 '22 06:09 arjunsoota

Last release was 2018. Not a single one of the 38+ contributors has commented in years.

duhmojo avatar Sep 26 '22 15:09 duhmojo

I know a doomed requested feature when I see one, but bump anyway.

HZSamir avatar Oct 05 '22 07:10 HZSamir

can we combine bootstrap tags and react bootstrap table next component?

HASSANI8046 avatar Dec 22 '22 10:12 HASSANI8046

I tried combined headers by using headerformater and columnformater headerFormatter: (column) => ( <><Row className="combine-col-header">Heading</Row> <Row gutter={24}> <Col span={12}>Sub heading one </Col> <Col span={12}>Sub heading two </Col> </Row> </> ), formatter: (cell, row, rowIndex, extraData) => ( <Row gutter={24}> <Col span={12}>{cell} </Col> <Col span={12}>{row.Subheadingtwo}</Col> </Row> )

image

Atchaya-Kodeeswaran avatar May 16 '23 05:05 Atchaya-Kodeeswaran

I finally got a chance to take another look at grouped headings. @Atchaya-Kodeeswaran your approach can of course work but we lose column sort, and all sortValue/filterValue/etc... all need to implement all grouped values into the combo grouped column. The format and filter definition functions can be implemented all at one, but sorting is gone. Your work around is fine for unsorted columns. Thanks for the contribution.

duhmojo avatar Jun 22 '23 17:06 duhmojo

Also, like every Node project this one has a million build dependencies and specialized tweaks. I tried patching it, but simply building is a challenge in itself.

duhmojo avatar Jun 23 '23 15:06 duhmojo

OK, I used patch-package to create a patch for header.js and bootstrap-table.js. I added a columnGroups table prop that takes an optional object ( { <column idx #>: { title: <''>, colspan: <#>, className: <> } ) and if set, I have some logic that creates a TD/TH row before the normal header row.

The styling and the real header row work out, sorting and filtering work. However I'll need to do a bit more work to deal with column widths which, though it can be set in headerStyle, only the top/highest TD width will dictate the column width. For nested heading to work you need a matching TD above the existing TDs, even if they're not colspanned with a title.

Here's my patch file:

diff --git a/node_modules/react-bootstrap-table-next/dist/react-bootstrap-table-next.js b/node_modules/react-bootstrap-table-next/dist/react-bootstrap-table-next.js
index 2b73668..b3a06b8 100644
--- a/node_modules/react-bootstrap-table-next/dist/react-bootstrap-table-next.js
+++ b/node_modules/react-bootstrap-table-next/dist/react-bootstrap-table-next.js
@@ -3144,6 +3144,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
 var Header = function Header(props) {
   var className = props.className,
       columns = props.columns,
+      columnGroups = props.columnGroups,
       onSort = props.onSort,
       onFilter = props.onFilter,
       sortField = props.sortField,
@@ -3213,9 +3214,46 @@ var Header = function Header(props) {
     }
   }
 
+  // { idx #: { title: <>, colspan: <#>, className: <> }
+  let headGroups = undefined
+  if (columnGroups) {
+    let colCount = 0
+    for (let i = 0; i < columns.length; i++) {
+      const columnGroup = columnGroups[i]
+      if (columnGroup) {
+        headGroups.push(
+          _react2.default.createElement(
+            'td',
+            { className: c.className },
+            { colspan: c.colspan },
+            c.title
+          )
+        )
+        colCount = c.colspan
+      } else {
+        // either this is a column to add a placeholder for, or a spaned column
+        if (colCount === 0) {
+          _react2.default.createElement(
+            'td',
+            { className: c.className }
+          )
+        }
+      }
+      if(colCount > 0) colCount -= 1
+    }
+  }
+
+  if (headGroups) {
+    headGroups = _react2.default.createElement(
+      'tr',
+      headGroups
+    )
+  }
+
   return _react2.default.createElement(
     'thead',
     { className: wrapperClasses },
+    headGroups,
     _react2.default.createElement(
       'tr',
       { className: className },
@@ -3225,6 +3263,7 @@ var Header = function Header(props) {
 };
 
 Header.propTypes = {
+  columnGroups: _propTypes2.default.object,
   columns: _propTypes2.default.array.isRequired,
   onSort: _propTypes2.default.func,
   onFilter: _propTypes2.default.func,
diff --git a/node_modules/react-bootstrap-table-next/lib/src/bootstrap-table.js b/node_modules/react-bootstrap-table-next/lib/src/bootstrap-table.js
index 4bb7a5e..468b90e 100644
--- a/node_modules/react-bootstrap-table-next/lib/src/bootstrap-table.js
+++ b/node_modules/react-bootstrap-table-next/lib/src/bootstrap-table.js
@@ -111,6 +111,7 @@ var BootstrapTable = function (_PropsBaseResolver) {
     value: function renderTable() {
       var _props2 = this.props,
           columns = _props2.columns,
+          columnGroups = _props2.columnGroups,
           keyField = _props2.keyField,
           tabIndexCell = _props2.tabIndexCell,
           id = _props2.id,
@@ -163,6 +164,7 @@ var BootstrapTable = function (_PropsBaseResolver) {
           tableCaption,
           _react2.default.createElement(_header2.default, {
             columns: columns,
+            columnGroups: this.props.columnGroups,
             className: this.props.headerClasses,
             wrapperClasses: this.props.headerWrapperClasses,
             sortField: this.props.sortField,
@@ -222,6 +224,7 @@ BootstrapTable.propTypes = {
   keyField: _propTypes2.default.string.isRequired,
   data: _propTypes2.default.array.isRequired,
   columns: _propTypes2.default.array.isRequired,
+  columnGroups: _propTypes2.default.object,
   bootstrap4: _propTypes2.default.bool,
   remote: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.shape({
     pagination: _propTypes2.default.bool
diff --git a/node_modules/react-bootstrap-table-next/lib/src/header.js b/node_modules/react-bootstrap-table-next/lib/src/header.js
index 968a435..752ae79 100644
--- a/node_modules/react-bootstrap-table-next/lib/src/header.js
+++ b/node_modules/react-bootstrap-table-next/lib/src/header.js
@@ -42,6 +42,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
 var Header = function Header(props) {
   var className = props.className,
       columns = props.columns,
+      columnGroups = props.columnGroups,
       onSort = props.onSort,
       onFilter = props.onFilter,
       sortField = props.sortField,
@@ -111,18 +112,56 @@ var Header = function Header(props) {
     }
   }
 
-  return _react2.default.createElement(
-    'thead',
-    { className: wrapperClasses },
-    _react2.default.createElement(
-      'tr',
-      { className: className },
-      childrens
-    )
-  );
+    // { idx #: { title: <>, colspan: <#>, className: <> }
+    let headGroups = []
+    if (columnGroups) {
+      let colCount = 0
+      for (let i = 0; i < columns.length; i++) {
+        const columnGroup = columnGroups[i]
+        if (columnGroup) {
+          headGroups.push(
+            _react2.default.createElement(
+              'th',
+              { className: columnGroup.className, colSpan: columnGroup.colspan },
+              columnGroup.title
+            )
+          )
+          colCount = columnGroup.colspan > 1 ? (columnGroup.colspan - 1) : columnGroup.colspan
+        } else {
+          // either this is a column to add a placeholder for, or a spaned column
+          if (colCount === 0) {
+            headGroups.push(_react2.default.createElement(
+              'th'
+            ))
+          }
+        }
+        if(colCount > 0) colCount -= 1
+      }
+    }
+  
+    let groupHeader = undefined
+    if (headGroups.length > 0) {
+      groupHeader = _react2.default.createElement(
+        'tr',
+        { className: className },
+        headGroups
+      )
+    }
+  
+    return _react2.default.createElement(
+      'thead',
+      { className: wrapperClasses },
+      groupHeader,
+      _react2.default.createElement(
+        'tr',
+        { className: className },
+        childrens
+      )
+    );
 };
 
 Header.propTypes = {
+  columnGroups: _propTypes2.default.object,
   columns: _propTypes2.default.array.isRequired,
   onSort: _propTypes2.default.func,
   onFilter: _propTypes2.default.func,

duhmojo avatar Jun 23 '23 20:06 duhmojo

Note that I account for the existence of the selectRow prop (the checkbox first column) and bump the index of which columns to colspan over by 1 in a component that includes BootstrapTable.

duhmojo avatar Jun 23 '23 20:06 duhmojo

You can create multi header by adding multiple

tags inside table header and using colSpan property.

And the result is: image

LG64BIT avatar Mar 06 '24 10:03 LG64BIT

You can create multi header by adding multiple tags inside table header and using colSpan property.

And the result is: image

Hi, Could you please provide the code how you're achieving this. Also, Filter and sorting are working or not after the implementations!

nazcoder avatar Mar 12 '24 07:03 nazcoder

Code: function BasicExample() { return ( <Table striped bordered hover> <thead> <tr> <th colSpan={3}>Personal</th> <th>Other</th> </tr> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Mark</td> <td>Otto</td> <td>@mdo</td> </tr> <tr> <td>2</td> <td>Jacob</td> <td>Thornton</td> <td>@fat</td> </tr> </tbody> </Table> ); } Haven't tried filtering and sorting, I don't see why it wouldn't work, also question was just about headers.

LG64BIT avatar Mar 12 '24 09:03 LG64BIT

You'll loose sorting. See my comment above and the other person that suggested something similar. Also your example doesn't appear to be related to this React component, it's just a table. In this component you can format the header and define columns, separately. Sorting doesn't automatically get attached to your own custom heading format. It's an integrated feature.

This should be a feature of this aging, but extremely useful component.

duhmojo avatar Mar 12 '24 16:03 duhmojo