5

I am following below example to implement "expand row by column".

/* eslint max-len: 0 */
import React from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';

const products = [];

function addProducts(quantity) {
  const startId = products.length;
  for (let i = 0; i < quantity; i++) {
    const id = startId + i;
    if (i < 3) {
      products.push({
        id: id,
        name: 'Item name ' + id,
        price: 2100 + i,
        expand: [ {
          fieldA: 'test1',
          fieldB: (i + 1) * 99,
          fieldC: (i + 1) * Math.random() * 100,
          fieldD: '123eedd' + i
        }, {
          fieldA: 'test2',
          fieldB: i * 99,
          fieldC: i * Math.random() * 100,
          fieldD: '123eedd' + i
        } ]
      });
    } else {
      products.push({
        id: id,
        name: 'Item name ' + id,
        price: 2100 + i
      });
    }
  }
}
addProducts(5);

class BSTable extends React.Component {
  render() {
    if (this.props.data) {
      return (
        <BootstrapTable data={ this.props.data }>
          <TableHeaderColumn dataField='fieldA' isKey={ true }>Field A</TableHeaderColumn>
          <TableHeaderColumn dataField='fieldB'>Field B</TableHeaderColumn>
          <TableHeaderColumn dataField='fieldC'>Field C</TableHeaderColumn>
          <TableHeaderColumn dataField='fieldD'>Field D</TableHeaderColumn>
        </BootstrapTable>);
    } else {
      return (<p>?</p>);
    }
  }
}

export default class ExpandRow extends React.Component {
  constructor(props) {
    super(props);
  }

  isExpandableRow(row) {
    if (row.id < 3) return true;
    else return false;
  }

  expandComponent(row) {
    return (
      <BSTable data={ row.expand } />
    );
  }

  render() {
    const options = {
      expandRowBgColor: 'rgb(242, 255, 163)',
      expandBy: 'column'  // Currently, available value is row and column, default is row
    };
    return (
      <BootstrapTable data={ products }
        options={ options }
        expandableRow={ this.isExpandableRow }
        expandComponent={ this.expandComponent }
        search>
        <TableHeaderColumn dataField='id' isKey={ true }>Product ID</TableHeaderColumn>
        <TableHeaderColumn dataField='name' expandable={ false }>Product Name</TableHeaderColumn>
        <TableHeaderColumn dataField='price' expandable={ false }>Product Price</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Questions: I want to implement expand row on "multiple columns". For eg:

I would make 2 columns out of 3 to expand rows.

Product ID Product Name Product Price

Behavior I want is :

1.) When user clicks on "product id" column, I want to show some other BSTTableNew component like above (on expand row) but with columns "field A" & "field B" and some other functionality.

2.) When user clicks on "product name" column, I want to show BSTTable (on expand row) with similarly as above.

What changes I have to make in below code to load respective component class based upon the column I click to expand row with additional details?

I believe i have to make some changes in below code to load other components:

expandComponent(row) {

if( column === "productID") { //something of this sort I want
  return (
    <BSTableNew data={ row.expand } />
  );
}

if( column === "productName") {  //something of this sort I want
  return (
    <BSTable data={ row.expand } />
  );
}
}

How to achieve above?

zubug55
  • 729
  • 7
  • 27

1 Answers1

6

react-bootstrap-table is deprecated, you should use react-bootstrap-table2


If I correctly understood requirements, you want to expand row but the expanded content should be different, depending on column/cell clicked.

1st - expanded rows

Taking 'Expand Management' example as a base we can see how to control expanded rows using an array in the state. It's easy but we can't use onExpand handler as not column dependent. We can use expanded option:

expanded: this.state.expanded,

This array contains only expanded rows indexes.

2nd - what column clicked ?

Examples contains 'Column Event' - onClick gets column param we need. This event must be defined in columns, f.e. sth like:

const columns = [{
  dataField: 'id',
  text: 'Product ID',
  events: {
    onClick: (e, column, columnIndex, row, rowIndex) => {
      console.log(row, column);
      const isRowExpanded = this.state.expanded.includes( row );
      this.setState( {
        column: 'id',
        expanded: isRowExpanded ? 
          this.state.expanded.filter(x => x !== row)
          : [...this.state.expanded, row]
      });
    }
  }
}, {
  dataField: 'name',
  text: 'Product Name',
  events: {
    onClick: (e, column, columnIndex, row,     rowIndex) => {
      console.log(row, column);
      const isRowExpanded =     this.state.expanded.includes( row );
      this.setState( {
        column: 'name',
        expanded: isRowExpanded ? 
          this.state.expanded.filter(x => x !== row)
          : [...this.state.expanded, row]
      });
    }
  }
}, {
  dataField: 'price',
  text: 'Product Price'
}];

This way we have both thing handled - expanded row and last clicked column.

3rd - display the appropriate component

We need only expanded renderer parametrization:

const expandRow = {
  renderer: row => {
    if (this.state.column==='id') {
      return (
        <ColumnIDClickedTable someParam={someData[row]} />
      )
    } else {
      return <ColumnNameClickedTable />
    }
  },

That should be all. Adding condition for only first 3 rows expandable is an easy task. All expanded rows will change the content on column change - only last click saved. Save column in indexed array if you need individual row behaviour.

xadm
  • 8,219
  • 3
  • 14
  • 25
  • Thanks for your answer. I have a query, clicking on cells on the same row should not close the expanded row, rather it should just change the content. Is there a way to achieve that ? – user1919581 Aug 26 '20 at 14:19
  • @user1919581 this solution should work like you need or can be easy adapted – xadm Aug 26 '20 at 15:39