react-bootstrap-table / react-bootstrap-table2

Next Generation of react-bootstrap-table
https://react-bootstrap-table.github.io/react-bootstrap-table2/
MIT License
1.27k stars 431 forks source link

Multiple Header Rows support? #617

Open bookworm2death opened 6 years ago

bookworm2death commented 6 years ago

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!

AllenFang commented 6 years ago

@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!

benkotch commented 5 years ago

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
arhimmel commented 5 years ago

@bookworm2death any luck with this?

benkotch commented 5 years ago

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

Fornori commented 5 years ago

any news about multi header?

tcboles commented 5 years ago

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

dstruyve commented 4 years ago

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.

thedmeyer commented 4 years ago

Any update?

amcm23 commented 4 years ago

Any update?

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

Ksenia0479 commented 4 years ago

Hi team

Any update on this?

Mikeez commented 4 years ago

I also would like to know 👍

josearaujo commented 3 years ago

Any update?

sashasemeniuk commented 3 years ago

Any update?

dennysemko commented 3 years ago

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

skg-thienpg commented 2 years ago

hi, any update?

duhmojo commented 2 years ago

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.

arjunsoota commented 2 years ago

Any update on this ? @AllenFang

duhmojo commented 2 years ago

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

HZSamir commented 2 years ago

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

HASSANI8046 commented 1 year ago

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

Atchaya-Kodeeswaran commented 1 year ago

I tried combined headers by using headerformater and columnformater ` headerFormatter: (column) => ( <>Heading

Sub heading one
                            <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
duhmojo commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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.

LG64BIT commented 8 months ago

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

And the result is: image

nazcoder commented 8 months ago

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!

LG64BIT commented 8 months ago

Code: `function BasicExample() { return (

Personal Other
# First Name Last Name Username
1 Mark Otto @mdo
2 Jacob Thornton @fat

); }` Haven't tried filtering and sorting, I don't see why it wouldn't work, also question was just about headers.

duhmojo commented 8 months ago

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.