React-table: SubComponent click entire row instead of just the arrow

Created on 16 Jun 2017  路  12Comments  路  Source: tannerlinsley/react-table

Hello,
I'm not sure how to allow clicking any part of a row will expand the subcomponent. I've been reading throught the documentation as well as some online articles but there isn't anything covering my specific requirement.

I've tried hooking into SubComponent and creating a div covering the entire row for onClick but that wasn't working for me either.

Thanks

Most helpful comment

I had a fairly simple table, but was able to achieve expanding rows on click with the following getTrProps change:

  getTrProps(state, rowInfo, col, instance) {
    return {
      onClick: (e) => {
        const { expanded } = state;
        const path = rowInfo.nestingPath[0];
        const diff = { [path]: expanded[path] ? false : true };

        instance.setState({
          expanded: {
            ...expanded,
            ...diff
          }
        });
      }
    };
  }

All 12 comments

You need to use getTrProps and provide an onClick handler for the entire row. getTrProps is a function that supplies you all of the information you'll need, including the viewIndex of the row.

In your onClick handler for the row, you will need to update and keep track of the opened and closed rows in your parent component and use the expanded controlled prop to send that model to the table. It is simply an object with keys that correspond to the rowIndex of the page and a value that can be truthy or falsey. eg.

{
  3: true,
  4: true,
  5: false,
  7: {
    2: true,
  }
}

The above object would result in rows 3, 4, 7 being expanded, including the 2nd sub row of the 7th row (if you have multiple nesting levels). As you can see, defining false for a row is possible, but not necessary as leaving it undefined is the same as being collapsed.

Hope this helps :)

Hi, I would also like to do that. I saw there is a onExpanderClick function. is there a way i can call it?

thanks

I know that is not the best approach, but this solution worked for me:

    onClickRow = (e) => {
        const row = $(e.target);
        $(row.parent().siblings())[0].        

        const columns = [{
            Header: 'Tag Name',
            id: 'label',
            Filter: getSearchFilter(),
            Cell: item =>  <div onClick={this.onClickRow}>
                {item.original.label}
            </div>
        }, {

this has worked for me:

expanded={this.state.expanded}
getTdProps={(state, rowInfo, column, instance) => { return { onClick: e => { this.expand_row(rowInfo) } } }}

where expand_row is a function changing the expanded state

is it possible to add some active class to the expanded rows dynamically ?

yes, via

getTrProps={(state, rowInfo, column) => {
          if(rowInfo != undefined)
          {
            if(state.expanded[rowInfo.viewIndex] == true)
            {
              return {
                className: <class that you want>,
                style:{
                  <style that you want>
                }
              }
            }
            else
            {
              return {
                className: <class that you want>,
                style:{
                  <style that you want>
                  }
              }
            }
          }
          else
            return {}
        }}

Thank you.

For anyone considering implementing this, I recommend reconsidering.

By controlling the 'expanded' state in your component or store, you'll need to also handle sorting, the original expander button, and your custom click implementation.

The documentation says to use handleOriginal() but if you're calling onClick() from elsewhere, handleOriginal is not defined.

Further, it's difficult to tell if a row is already expanded because isExpanded is not passed to row when rendering Cell, only Expander.

Still working through this problem. Hope to post my complete solution if I don't backtrack before then.

I had a fairly simple table, but was able to achieve expanding rows on click with the following getTrProps change:

  getTrProps(state, rowInfo, col, instance) {
    return {
      onClick: (e) => {
        const { expanded } = state;
        const path = rowInfo.nestingPath[0];
        const diff = { [path]: expanded[path] ? false : true };

        instance.setState({
          expanded: {
            ...expanded,
            ...diff
          }
        });
      }
    };
  }

@NathanCH have you managed to expand on row-click without having to completely control <ReactTable>?

I have a component created on top of (to set some defaults, styles, etc.) which is totally un-opinionated in regards to whether ReactTable is controlled or not (i.e. if, somewhere, I need to use MyTable and control it, that's just fine).
The problem is that I need row-click-to-expand as the default behaviour.
This requires me to use getTrProps and control the state in MyTable PLUS take care of all cases and edge cases (probably via getDerivedStateFromProps)

Thanks for all the comments guys! They were super helpful. Just to follow up with a full solution -- here is the component that I built from these comments.

export class ExpandableReportTable extends React.Component {
  constructor() {
    super();
    this.state = {
      expanded: null
    };
  }

  expand_row(row) {
    var expanded = {...this.state.expanded};
    if (expanded[row.index]) {
      expanded[row.index] = !expanded[row.index];
    } else {
      expanded[row.index] = true;
    }

    console.log(expanded);
    this.setState({
      expanded: expanded
    });
  }

  render() {

    return (
      <ReactTable
        columns={this.props.columns}
        data={this.props.data}
        expanded={this.state.expanded}
        getTdProps={(state, rowInfo, column, instance) => {
          return {
            onClick: e => {
              this.expand_row(rowInfo);
            }
          };
        }}
        SubComponent={d => {
          console.log('sub component: ', d);
          return <div>boop!</div>;
        }}
      />
    );
  }
}

It toggles a row's expansion on click and renders a subcomponent of "boop"

@jpribyl your solution looks pretty good to me. without trying it out, i think that you should use the property viewIndex instead of index. afaik viewIndex takes sorting and filtering into consideration, whereas index does not. So you would use
expanded[row.viewIndex] and so on. Hope that helps

Was this page helpful?
0 / 5 - 0 ratings

Related issues

krishna-shenll picture krishna-shenll  路  3Comments

alexanderwhatley picture alexanderwhatley  路  3Comments

missmellyg85 picture missmellyg85  路  3Comments

bdkersey picture bdkersey  路  3Comments

kieronsutton00 picture kieronsutton00  路  3Comments